treequel 1.4.1 → 1.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. data.tar.gz.sig +0 -0
  2. data/bin/treequel +93 -50
  3. data/lib/treequel.rb +3 -3
  4. metadata +2 -2
  5. metadata.gz.sig +0 -0
data.tar.gz.sig CHANGED
Binary file
@@ -70,6 +70,10 @@ module IRB # :nodoc:
70
70
  end
71
71
 
72
72
  # The Treequel shell.
73
+ #
74
+ # TODO:
75
+ # * Make more commands use the convert_to_branchsets utility function
76
+ #
73
77
  class Treequel::Shell
74
78
  include Readline,
75
79
  Treequel::Loggable,
@@ -299,6 +303,7 @@ class Treequel::Shell
299
303
  else
300
304
  self.handle_missing_cmd( command )
301
305
  end
306
+
302
307
  rescue LDAP::ResultError => err
303
308
  case err.message
304
309
  when /can't contact ldap server/i
@@ -318,6 +323,10 @@ class Treequel::Shell
318
323
  error_message( err.class.name, err.message )
319
324
  self.log.debug { " " + err.backtrace.join(" \n") }
320
325
  end
326
+
327
+ rescue => err
328
+ error_message( err.message )
329
+ self.log.debug { " " + err.backtrace.join(" \n") }
321
330
  end
322
331
 
323
332
 
@@ -418,6 +427,10 @@ class Treequel::Shell
418
427
  def show_completions_command
419
428
  message "Completions:", @completions.inspect
420
429
  end
430
+ set_options :show_completions do |oparser, options|
431
+ oparser.banner = "show_completions"
432
+ oparser.separator 'Show the list of command completions (for debugging the shell)'
433
+ end
421
434
 
422
435
 
423
436
  ### Show help text for the specified command, or a list of all available commands
@@ -428,9 +441,11 @@ class Treequel::Shell
428
441
  message colorize( "Available commands", :bold, :white ),
429
442
  *columnize(@commands)
430
443
  else
431
- cmd = args.shift.to_sym
432
- if @@option_parsers.key?( cmd )
433
- oparser, _ = @@option_parsers[ cmd ]
444
+ cmd = args.shift
445
+ full_command = @completions[ cmd ]
446
+
447
+ if @@option_parsers.key?( full_command.to_sym )
448
+ oparser, _ = @@option_parsers[ full_command.to_sym ]
434
449
  self.log.debug "Setting summary width to: %p" % [ @columns ]
435
450
  oparser.summary_width = @columns
436
451
  output = oparser.to_s.sub( /^(.*?)\n/ ) do |match|
@@ -440,7 +455,7 @@ class Treequel::Shell
440
455
  $stderr.puts
441
456
  message( output )
442
457
  else
443
- error_message( "No help for '#{cmd.inspect}'" )
458
+ error_message( "No help for '#{cmd}'" )
444
459
  end
445
460
  end
446
461
  end
@@ -455,7 +470,7 @@ class Treequel::Shell
455
470
  message "Okay, exiting."
456
471
  self.quit = true
457
472
  end
458
- set_options :help do |oparser, options|
473
+ set_options :quit do |oparser, options|
459
474
  oparser.banner = "quit"
460
475
  oparser.separator 'Exit the shell.'
461
476
  end
@@ -488,6 +503,7 @@ class Treequel::Shell
488
503
 
489
504
  ### Display LDIF for the specified RDNs.
490
505
  def cat_command( options, *args )
506
+ validate_rdns( *args )
491
507
  args.each do |rdn|
492
508
  extended = rdn.chomp!( '+' )
493
509
 
@@ -512,6 +528,7 @@ class Treequel::Shell
512
528
 
513
529
  ### Display YAML for the specified RDNs.
514
530
  def yaml_command( options, *args )
531
+ validate_rdns( *args )
515
532
  args.each do |rdn|
516
533
  branch = @currbranch.get_child( rdn )
517
534
  message( branch_as_yaml(branch) )
@@ -534,6 +551,7 @@ class Treequel::Shell
534
551
 
535
552
  # Otherwise, list each one specified
536
553
  else
554
+ validate_rdns( *args )
537
555
  args.each do |rdn|
538
556
  if branch = @currbranch.get_child( rdn )
539
557
  targets << branch
@@ -545,11 +563,13 @@ class Treequel::Shell
545
563
 
546
564
  # Fetch each branch's children, sort them, format them in columns, and highlight them
547
565
  targets.each do |branch|
566
+ header( branch.dn ) if targets.length > 1
548
567
  if options.longform
549
568
  message self.make_longform_ls_output( branch, options )
550
569
  else
551
570
  message self.make_shortform_ls_output( branch, options )
552
571
  end
572
+ message if targets.length > 1
553
573
  end
554
574
  end
555
575
  set_options :ls do |oparser, options|
@@ -575,46 +595,6 @@ class Treequel::Shell
575
595
  end
576
596
 
577
597
 
578
- ### Generate long-form output lines for the 'ls' command for the given +branch+.
579
- def make_longform_ls_output( branch, options )
580
- children = branch.children
581
- header = colorize( :underscore, :cyan ) { "total %d" % [children.length] }
582
-
583
- # Calcuate column widths
584
- oclen = children.map do |subbranch|
585
- subbranch.include_operational_attrs = true
586
- subbranch[:structuralObjectClass] ? subbranch[:structuralObjectClass].length : 0
587
- end.max
588
-
589
- # Set up sorting by collecting all the requested sort criteria as Proc objects which
590
- # will be applied
591
- sortfuncs = []
592
- sortfuncs << lambda {|subbranch| subbranch[:hasSubordinates] ? 0 : 1 } if options.dirsort
593
- sortfuncs << lambda {|subbranch| subbranch[:modifyTimestamp] } if options.timesort
594
- sortfuncs << lambda {|subbranch| subbranch.rdn.downcase }
595
-
596
- rows = children.
597
- sort_by {|subbranch| sortfuncs.collect {|func| func.call(subbranch) } }.
598
- collect {|subbranch| self.format_description(subbranch, oclen) }
599
-
600
- return [ header ] + (options.reversesort ? rows.reverse : rows)
601
- end
602
-
603
-
604
- ### Generate short-form 'ls' output for the given +branch+ and return it.
605
- def make_shortform_ls_output( branch, options )
606
- branch.include_operational_attrs = true
607
- entries = branch.children.
608
- collect {|b| b.rdn + (b[:hasSubordinates] ? '/' : '') }.
609
- sort_by {|rdn| rdn.downcase }
610
- self.log.debug "Displaying %d entries in short form." % [ entries.length ]
611
-
612
- return columnize( entries ).gsub( /#{ATTRIBUTE_TYPE}=\s*\S+/ ) do |rdn|
613
- format_rdn( rdn )
614
- end
615
- end
616
-
617
-
618
598
  ### Change the current working DN to +rdn+.
619
599
  def cdn_command( options, rdn=nil, *args )
620
600
  if rdn.nil?
@@ -624,7 +604,7 @@ class Treequel::Shell
624
604
 
625
605
  return self.parent_command( options ) if rdn == '..'
626
606
 
627
- raise "invalid RDN %p" % [ rdn ] unless RELATIVE_DISTINGUISHED_NAME.match( rdn )
607
+ validate_rdns( rdn )
628
608
 
629
609
  pairs = rdn.split( /\s*,\s*/ )
630
610
  pairs.each do |dnpair|
@@ -655,6 +635,7 @@ class Treequel::Shell
655
635
 
656
636
  # ### Create the entry specified by +rdn+.
657
637
  def create_command( options, rdn )
638
+ validate_rdns( rdn )
658
639
  branch = @currbranch.get_child( rdn )
659
640
 
660
641
  raise "#{branch.dn}: already exists." if branch.exists?
@@ -668,6 +649,7 @@ class Treequel::Shell
668
649
 
669
650
  ### Edit the entry specified by +rdn+.
670
651
  def edit_command( options, rdn )
652
+ validate_rdns( rdn )
671
653
  branch = @currbranch.get_child( rdn )
672
654
 
673
655
  raise "#{branch.dn}: no such entry. Did you mean to 'create' it instead? " unless
@@ -687,6 +669,7 @@ class Treequel::Shell
687
669
 
688
670
  ### Change the DN of an entry
689
671
  def mv_command( options, rdn, newdn )
672
+ validate_rdns( rdn, newdn )
690
673
  branch = @currbranch.get_child( rdn )
691
674
 
692
675
  raise "#{branch.dn}: no such entry" unless branch.exists?
@@ -702,6 +685,8 @@ class Treequel::Shell
702
685
 
703
686
  ### Copy an entry
704
687
  def cp_command( options, rdn, newrdn )
688
+ # Can't validate as RDNs because they might be full DNs
689
+
705
690
  base_dn = @currbranch.directory.base_dn
706
691
 
707
692
  # If the RDN includes the base, it's a DN
@@ -737,6 +722,7 @@ class Treequel::Shell
737
722
 
738
723
  ### Remove the entry specified by +rdn+.
739
724
  def rm_command( options, *rdns )
725
+ validate_rdns( *rdns )
740
726
  branchsets = self.convert_to_branchsets( *rdns )
741
727
  coll = Treequel::BranchCollection.new( *branchsets )
742
728
 
@@ -838,7 +824,9 @@ class Treequel::Shell
838
824
  if args.empty?
839
825
  branch = @currbranch
840
826
  else
841
- branch = @currbranch.get_child( args.first )
827
+ rdn = args.first
828
+ validate_rdns( rdn )
829
+ branch = @currbranch.get_child( rdn )
842
830
  end
843
831
 
844
832
  self.log.debug "Setting up IRb shell"
@@ -869,6 +857,10 @@ class Treequel::Shell
869
857
  end
870
858
 
871
859
 
860
+ #################################################################
861
+ ### U T I L I T Y M E T H O D S
862
+ #################################################################
863
+
872
864
  ### Convert the given +patterns+ to branchsets relative to the current branch and return
873
865
  ### them. This is used to map shell arguments like 'cn=*', 'Hosts', 'cn=dav*' into
874
866
  ### branchsets that will find matching entries.
@@ -882,9 +874,45 @@ class Treequel::Shell
882
874
  end
883
875
 
884
876
 
885
- #################################################################
886
- ### U T I L I T Y M E T H O D S
887
- #################################################################
877
+ ### Generate long-form output lines for the 'ls' command for the given +branch+.
878
+ def make_longform_ls_output( branch, options )
879
+ children = branch.children
880
+ totalmsg = "total %d" % [ children.length ]
881
+
882
+ # Calcuate column widths
883
+ oclen = children.map do |subbranch|
884
+ subbranch.include_operational_attrs = true
885
+ subbranch[:structuralObjectClass] ? subbranch[:structuralObjectClass].length : 0
886
+ end.max
887
+
888
+ # Set up sorting by collecting all the requested sort criteria as Proc objects which
889
+ # will be applied
890
+ sortfuncs = []
891
+ sortfuncs << lambda {|subbranch| subbranch[:hasSubordinates] ? 0 : 1 } if options.dirsort
892
+ sortfuncs << lambda {|subbranch| subbranch[:modifyTimestamp] } if options.timesort
893
+ sortfuncs << lambda {|subbranch| subbranch.rdn.downcase }
894
+
895
+ rows = children.
896
+ sort_by {|subbranch| sortfuncs.collect {|func| func.call(subbranch) } }.
897
+ collect {|subbranch| self.format_description(subbranch, oclen) }
898
+
899
+ return [ totalmsg ] + (options.reversesort ? rows.reverse : rows)
900
+ end
901
+
902
+
903
+ ### Generate short-form 'ls' output for the given +branch+ and return it.
904
+ def make_shortform_ls_output( branch, options )
905
+ branch.include_operational_attrs = true
906
+ entries = branch.children.
907
+ collect {|b| b.rdn + (b[:hasSubordinates] ? '/' : '') }.
908
+ sort_by {|rdn| rdn.downcase }
909
+ self.log.debug "Displaying %d entries in short form." % [ entries.length ]
910
+
911
+ return columnize( entries ).gsub( /#{ATTRIBUTE_TYPE}=\s*\S+/ ) do |rdn|
912
+ format_rdn( rdn )
913
+ end
914
+ end
915
+
888
916
 
889
917
  ### Return the description of the specified +branch+ suitable for displaying in
890
918
  ### the directory listing.
@@ -1004,6 +1032,13 @@ class Treequel::Shell
1004
1032
  end
1005
1033
 
1006
1034
 
1035
+ ### Output a header containing the given +text+.
1036
+ def header( text )
1037
+ header = colorize( text, :underscore, :cyan )
1038
+ $stderr.puts( header )
1039
+ end
1040
+
1041
+
1007
1042
  ### Output the specified message +parts+.
1008
1043
  def message( *parts )
1009
1044
  $stderr.puts( *parts )
@@ -1185,6 +1220,14 @@ class Treequel::Shell
1185
1220
  end
1186
1221
 
1187
1222
 
1223
+ ### Raise a RuntimeError if the specified +rdn+ is invalid.
1224
+ def validate_rdns( *rdns )
1225
+ rdns.flatten.each do |rdn|
1226
+ raise "invalid RDN %p" % [ rdn ] unless RELATIVE_DISTINGUISHED_NAME.match( rdn )
1227
+ end
1228
+ end
1229
+
1230
+
1188
1231
  ### Return an ANSI-colored version of the given +rdn+ string.
1189
1232
  def format_rdn( rdn )
1190
1233
  rdn.split( /,/ ).collect do |rdn_part|
@@ -25,7 +25,7 @@ end
25
25
 
26
26
  # A library for interacting with LDAP modelled after Sequel.
27
27
  #
28
- # @version 1.3.0
28
+ # @version 1.4.2
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.4.1'
56
+ VERSION = '1.4.2'
57
57
 
58
58
  # VCS revision
59
- REVISION = %q$Revision: 72213abfe94d $
59
+ REVISION = %q$Revision: a48b3d18545c $
60
60
 
61
61
  # Common paths for ldap.conf
62
62
  COMMON_LDAP_CONF_PATHS = %w[
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 1
7
7
  - 4
8
- - 1
9
- version: 1.4.1
8
+ - 2
9
+ version: 1.4.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - Michael Granger
metadata.gz.sig CHANGED
Binary file