Module: Development

Defined in:
lib/development.rb

Overview

Singleton that manages configurations and requires.

Defined Under Namespace

Modules: Exception, Require

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.clearDevelopment

Reset internal tracking variables.

Returns:



212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/development.rb', line 212

def self.clear
  
  @enabled_gems.clear
  @disabled_gems.clear
  @gemsets.clear
  @general_load_paths.clear
  @loaded_gems.clear
  @named_directories.clear
  
  return self
  
end

.create_gemset(gemset_name) ⇒ Array

Create gemset with name.

Parameters:

  • gemset_name

    Name of gemset.

Returns:

  • (Array)

    Gemset.



642
643
644
645
646
647
648
649
650
651
652
# File 'lib/development.rb', line 642

def self.create_gemset( gemset_name )

  gemset_name = gemset_name.to_sym
  
  unless gemset = @gemsets[ gemset_name ]
    @gemsets[ gemset_name ] = gemset = ::Array::Unique.new
  end
  
  return gemset
  
end

.directory(directory_name) ⇒ String

Return path for directory name.

Parameters:

  • directory_name

    Name of named directory.

Returns:

  • (String)

    Directory path associated with directory name.



41
42
43
44
45
# File 'lib/development.rb', line 41

def self.directory( directory_name )

  return @named_directories[ directory_name.to_sym ]
  
end

.disabled_gemsArray<Symbol>

Get gems that have been explicitly disabled.

Returns:

  • (Array<Symbol>)

    Array of gem or gemset names.



116
117
118
119
120
# File 'lib/development.rb', line 116

def self.disabled_gems

  return @disabled_gems

end

.enabled_for_all?true, false

Query whether Development is set to search in general paths for any gem, even if not explicitly enabled.

Returns:

  • (true, false)

    Whether general gem search is enabled.



86
87
88
89
90
# File 'lib/development.rb', line 86

def self.enabled_for_all?
  
  return @enable_for_all
  
end

.enabled_gemsArray<Symbol>

Get gems that have been explicitly enabled.

Returns:

  • (Array<Symbol>)

    Array of gem or gemset names.



101
102
103
104
105
# File 'lib/development.rb', line 101

def self.enabled_gems
  
  return @enabled_gems
  
end

.gem_name_at_load_path?(load_path, gem_directory_name, require_gem_at_path = false) ⇒ true, false

Query whether gem name is present at load path.

Parameters:

  • load_path

    Path where gem directory might be located.

  • gem_directory_name

    Name of gem. Assumes gem-subname is used rather than gem/subname.

Returns:

  • (true, false)

    Whether gem name is present.



926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
# File 'lib/development.rb', line 926

def self.gem_name_at_load_path?( load_path, gem_directory_name, require_gem_at_path = false )
  
  exists_at_load_path = false
  
  gem_name = gem_directory_name.gsub( '-', '/' )
  gem_path = ::File.join( load_path, gem_directory_name )
  
  gem_require_file = ::File.join( gem_path, 'lib', gem_name ) + '.rb'
  
  if ::Dir.exist?( ::File.expand_path( gem_path ) ) and 
     ::File.exist?( ::File.expand_path( gem_require_file ) )
    
    exists_at_load_path = true
  
  end
  
  return exists_at_load_path
  
end

.gemset(gemset_name) ⇒ Array

Get gemset with name.

Parameters:

  • gemset_name

    Name of gemset.

Returns:

  • (Array)

    Gemset.



667
668
669
670
671
# File 'lib/development.rb', line 667

def self.gemset( gemset_name )
  
  return @gemsets[ gemset_name.to_sym ]
  
end

.gemsetsHash{Symbol=>Array<Symbol>}

Get hash of gemsets and their gem or gemset members.

Returns:

  • (Hash{Symbol=>Array<Symbol>})

    Hash of gemsets and their gem or gemset members.



131
132
133
134
135
# File 'lib/development.rb', line 131

def self.gemsets
  
  return @gemsets
  
end

.general_load_pathsArray<String>

Get Array of paths that will be used for general loading purposes if a specific gem path is not given.

Returns:

  • (Array<String>)

    Paths to be used for general loading purposes.



56
57
58
59
60
# File 'lib/development.rb', line 56

def self.general_load_paths

  return @general_load_paths

end

.load_configuration_file(path) ⇒ Object

Load configuration file.

Looks first in project directory, second in home directory. 
If configuration file is not found in project directory, Development will not load.


234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
# File 'lib/development.rb', line 234

def self.load_configuration_file( path )
      
  # we build up a configuration line and process when we reach its end (the next line)
  expression_string = ''

  configuration_file_path = ::File.expand_path( path )
  
  @line_number = 0

  ::File.open( configuration_file_path ).each_with_index do |this_line, this_line_number|
  
    # when parse_configuration_file_line returns false we have a complete expression
    while parse_configuration_file_line( expression_string, this_line )

      # process expression_string
      parse_configuration_expression( expression_string )

      # reset expression_string
      expression_string.clear
      
      # update line number where expression begins
      @line_number = this_line_number
      unless this_line.empty?
        @line_number += 1
      end
      
      # loop will cause start with this_line, which told parse_configuration_file_line 
      # that we were done, and which is therefore not yet processed
      
    end

  end

  parse_configuration_expression( expression_string )
  
end

.load_gem_from_path(load_path, gem_directory_name) ⇒ true, false

Load gem from gem path. Assumes gem is present at path.

Parameters:

  • load_path

    Path where gem directory might be located.

  • gem_directory_name

    Name of gem. Assumes gem-subname is used rather than gem/subname.

Returns:

  • (true, false)

    Whether gem name is present.



963
964
965
966
967
968
969
970
971
972
# File 'lib/development.rb', line 963

def self.load_gem_from_path( load_path, gem_directory_name )
      
  gem_name = gem_directory_name.gsub( '-', '/' )
  gem_path = ::File.join( load_path, gem_directory_name )
  
  gem_require_file = ::File.join( gem_path, 'lib', gem_name ) + '.rb'
  
  require_relative( ::File.expand_path( gem_require_file ) )
  
end

.location(location_name) ⇒ Array<Symbol>

Get gems or gemsets associated with location.

Parameters:

  • location_name

    Name of location.

Returns:

  • (Array<Symbol>)


165
166
167
168
169
# File 'lib/development.rb', line 165

def self.location( location_name )
  
  return @locations[ location_name.to_sym ]
  
end

.locationsHash{Symbol=>Array{String}]

Hash of locations and the gems or gemsets located at each.

Returns:

  • (Hash{Symbol=>Array{String}])

    HashSymbol=>Array{String]



146
147
148
149
150
# File 'lib/development.rb', line 146

def self.locations
  
  return @locations
  
end

.named_directoriesHash{Symbol=>String}

Get Hash of named directory names to paths.

Returns:

  • (Hash{Symbol=>String})


71
72
73
74
75
# File 'lib/development.rb', line 71

def self.named_directories

  return @named_directories

end

.parse_base_action_from_expression_string(expression_string) ⇒ String

Parse signal character (+, -, =, @, !) and base action string from expression.

Parameters:

  • expression_string

    Expression string.

Returns:

  • (String)

    Base action string.



497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
# File 'lib/development.rb', line 497

def self.parse_base_action_from_expression_string( expression_string )
  
  base_action = nil
  
  # get rid of =
  expression_string.slice!( 0, 1 )
  
  if whitespace_index = expression_string =~ /\s/
    base_action = expression_string.slice!( 0, whitespace_index )
  else
    base_action = expression_string.dup
    expression_string.clear
  end
  
  expression_string.strip!

  return base_action
  
end

.parse_configuration_expression(expression_string) ⇒ Object

Parse single configuration expression built up from one or more actual configuration file lines.

Parameters:

  • expression_string

    String describing configuration directive.

Returns:



342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
# File 'lib/development.rb', line 342

def self.parse_configuration_expression( expression_string )
  
  case expression_string[ 0 ]
    
    # + - named directory expression
    when '+'

      # either a directory definition or a general directory directive
      # directory definitions are multiplart, whereas general directory definitions are one part
      parse_named_directory_expression( expression_string )
              
    # - - remove general path
    when '-'

      parse_remove_general_load_path_expression( expression_string )

    # = - gemset expression
    when '='

      parse_gemset_expression( expression_string )

    # @ - location expression
    when '@'

      parse_general_directory_or_location_expression( expression_string )

    # ! - enable/disable expression
    when '!'

      parse_enable_disable_expression( expression_string )
    
    # general path expression
    else

      parse_general_load_path_expression( expression_string )
    
  end
  
  return self
  
end

.parse_configuration_file_line(expression_string, configuration_file_line, continuation = false) ⇒ true, false

Parses configuration_file_line to construct expression_string from multiple configuration_file_lines.

Parameters:

  • expression_string

    Configuration expression that spans one or more lines in configuration file.

  • configuration_file_line

    Literal line from configuration file (may only be part of an expression).

Returns:

  • (true, false)

    Whether expression is still complete. True means configuration_file_line was not processed.



289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
# File 'lib/development.rb', line 289

def self.parse_configuration_file_line( expression_string, configuration_file_line, continuation = false )

  expression_complete = false

  # if we begin with a comment we can throw away the line
  if configuration_file_line[ 0 ] == '#'
    
    # nothing to do - we just ignore the line
    
  # if we begin with whitespace we have a continuation
  elsif configuration_file_line[ 0 ] =~ /\s/
    
    configuration_file_line.strip!
    
    expression_complete = parse_configuration_file_line( expression_string, configuration_file_line, true )
  
  elsif continuation
    
    unless expression_string.empty?
      unless configuration_file_line.empty?
        expression_string << ' '
      end
    end
    expression_string << configuration_file_line.strip

  elsif expression_string.empty?
    
    expression_string.replace( configuration_file_line.strip )
  
  # otherwise we reached the next line of the configuration file
  else

    expression_complete = true

  end
  
  return expression_complete
  
end

.parse_enable_disable_expression(expression_string) ⇒ Object

Parse expression string that has been determined as a enable/disable expression.

Parameters:

  • expression_string

    String describing enable/disable expression.

Returns:



731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
# File 'lib/development.rb', line 731

def self.parse_enable_disable_expression( expression_string )
  
  # !enable
  # !disable
  # !enable gem_or_set_name[,] ...
  # !disable gem_or_set_name[,] ...
  
  # enable or disable
  enable_or_disable = parse_base_action_from_expression_string( expression_string )
  
  gems = nil
  unless expression_string.empty?
    gems = ::Array::Unique.new
    parse_gem_names_from_expression_string( gems, expression_string )
  end
  
  case enable_or_disable = enable_or_disable.to_sym
    
    when :enable
      
      if gems
        gems.each do |this_gem, true_value|
          @enabled_gems.push( this_gem )
          @disabled_gems.delete( this_gem )
        end
      else
        @disabled_gems.delete_if do |this_gem, true_value|
          @enabled_gems.push( this_gem )
          true
        end
        @enable_for_all = true
      end
      
    when :disable

      if gems
        gems.each do |this_gem, true_value|
          @disabled_gems.push( this_gem )
          @enabled_gems.delete( this_gem )
        end
      else
        @enabled_gems.delete_if do |this_gem, true_value|
          @disabled_gems.push( this_gem )
          true
        end 
        @enable_for_all = false
      end
      
  end
  
  # do we have gems?
  
  return self
  
end

.parse_gem_name_from_expression_string(array, expression_string, slice_to_index, require_exist = false) ⇒ Symbol

Helper method to slice gem name from expression string and add or subtract from gemset.

Parameters:

  • array

    Array to add parsed data to.

  • gemset

    Gemset instance.

  • expression_string

    Expression string.

  • slice_to_index

    Index to slice expression string to.

  • require_exist (true, false) (defaults to: false)

    Raise exception if gems do not exist.

Returns:

  • (Symbol)

    Parsed gem name.



580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
# File 'lib/development.rb', line 580

def self.parse_gem_name_from_expression_string( array, expression_string, slice_to_index, require_exist = false )
  
  gem_name = expression_string.slice!( 0, slice_to_index )

  unless gem_name.empty?
          
    case gem_name[ -1 ]
      when ','
        gem_name.slice!( -1, 1 )
    end
  
    should_add = true
    
    case gem_name[ 0 ]
      when '+'
        gem_name.slice!( 0, 1 )
      when '-'
        gem_name.slice!( 0, 1 )
        array.delete( gem_name.to_sym )
        should_add = false
      else
    end

    # ensure we have 'gem-subname' rather than 'gem/subname'
    # we really just need one or the other consistently
    gem_name.gsub!( '/', '-' )

    gem_name = gem_name.to_sym

    if require_exist
      unless @enabled_gems.has_key?( gem_name ) or 
             @disabled_gems.has_key?( gem_name ) or 
             @gemsets.has_key?( gem_name)
        raise Exception::ExpressionError::UnknownGemOrGemsetName.new( gem_name, @line_number )
      end
    end

    if should_add
      array.push( gem_name )
    end
    
    expression_string.strip!

  end
  
  return gem_name
  
end

.parse_gem_names_from_expression_string(array, expression_string, require_exist = false) ⇒ Development

Parse gem name list separated by optional comma and white space from expression.

Parameters:

  • array

    Array to add parsed data to.

  • expression_string

    Expression string.

  • require_exist (true, false) (defaults to: false)

    Raise exception if gems do not exist.

Returns:



538
539
540
541
542
543
544
545
546
547
548
549
# File 'lib/development.rb', line 538

def self.parse_gem_names_from_expression_string( array, expression_string, require_exist = false )

  while next_whitespace_index = expression_string =~ /\s/
    parse_gem_name_from_expression_string( array, expression_string, next_whitespace_index )
  end

  # also slice till the end
  parse_gem_name_from_expression_string( array, expression_string, expression_string.length, require_exist )
  
  return self
  
end

.parse_gemset_expression(expression_string) ⇒ Object

Parse expression string that has been determined as a gemset expression.

Parameters:

  • expression_string

    String describing gemset expression.

Returns:



468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
# File 'lib/development.rb', line 468

def self.parse_gemset_expression( expression_string )

  # =gemset gem_or_set_name[,] ...
  # =gemset +gem_or_set_name[,] ...
  # =gemset -gem_or_set_name[,] ...

  gemset_name = parse_base_action_from_expression_string( expression_string )

  gemset = create_gemset( gemset_name )
  
  parse_gem_names_from_expression_string( gemset, expression_string )
  
  return self
  
end

.parse_general_directory_or_location_expression(expression_string) ⇒ Object

Parse expression string that has been determined as either a general path or location expression.

Parameters:

  • expression_string

    String describing general path or location expression.

Returns:



397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
# File 'lib/development.rb', line 397

def self.parse_general_directory_or_location_expression( expression_string )
  
  # if we have multiple parts
  if whitespace_index = expression_string =~ /\s/
    
    parse_location_expression( expression_string )
  
  # if we have one part
  else
    
    parse_general_load_path_expression( expression_string )
    
  end
  
  return self
  
end

.parse_general_load_path_expression(expression_string) ⇒ Object

Parse expression string that has been determined as a general directory expression.

Parameters:

  • expression_string

    String describing general directory expression.

Returns:



800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
# File 'lib/development.rb', line 800

def self.parse_general_load_path_expression( expression_string )
  
  # path/to/directory, ~/path/to/directory, /path/to/directory
  # +directory_name/path/from/directory
  
  case expression_string[ 0 ]
    
    when '@'

      path_parts = expression_string.split( '/' )
      named_directory = path_parts.shift
      named_directory.slice!( 0, 1 )
      named_directory = named_directory.to_sym
      expression_string = ::File.expand_path( ::File.join( directory( named_directory ), path_parts ) )
    
  end
  
  @general_load_paths.push( ::File.expand_path( expression_string ) )
  
  return self
  
end

.parse_location_expression(expression_string) ⇒ Object

Parse expression string that has been determined as a location expression.

Parameters:

  • expression_string

    String describing location expression.

Returns:



686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
# File 'lib/development.rb', line 686

def self.parse_location_expression( expression_string )
  
  # @directory_name gem_or_set_name[,] ...
  
  directory_name = parse_base_action_from_expression_string( expression_string )
  
  directory_name = directory_name.to_sym
  
  unless @named_directories.has_key?( directory_name )
    raise Exception::MalformedExpression::UnknownDirectoryName.new( directory_name, @line_number )
  end
  
  unless directory_members = @locations[ directory_name ]
    @locations[ directory_name ] = directory_members = ::Array::Unique.new
  end
  
  parse_gem_names_from_expression_string( directory_members, expression_string )
  
  directory_members.each do |this_gem_or_gemset|
    if gemset = @gemsets[ this_gem_or_gemset ]
      gemset.each do |this_gem|
        @gem_locations[ this_gem ] = directory_name
      end
    else
      @gem_locations[ this_gem_or_gemset ] = directory_name
    end
  end
  
  return self
  
end

.parse_named_directory_expression(expression_string) ⇒ Object

Parse expression string that has been determined as a named directory expression.

Parameters:

  • expression_string

    String describing named directory expression.

Returns:



428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
# File 'lib/development.rb', line 428

def self.parse_named_directory_expression( expression_string )
  
  # +directory_name path

  unless whitespace_index = expression_string =~ /\s/
    raise Exception::MalformedExpression::
          MalformedNamedDirectoryExpression.new( expression_string, @line_number )
  end

  directory_name = expression_string.slice( 1, whitespace_index - 1 )
  slice_length = expression_string.length - whitespace_index
  path = expression_string.slice( whitespace_index + 1, slice_length ).strip

  case path[0]
    when '@'
      path_parts = path.split( '/' )
      named_path_name = path_parts.shift
      named_path_name.slice!( 0, 1 )
      path = ::File.join( directory( named_path_name ), path_parts )
  end
  
  @named_directories[ directory_name.to_sym ] = ::File.expand_path( path )
  
  return self
  
end

.parse_remove_general_load_path_expression(expression_string) ⇒ Object

Parse expression string that has been determined as a remove-general-directory expression.

Parameters:

  • expression_string

    String describing remove general directory expression.

Returns:



836
837
838
839
840
841
842
843
844
845
846
847
848
# File 'lib/development.rb', line 836

def self.parse_remove_general_load_path_expression( expression_string )
  
  # -path/to/directory, -~/path/to/directory, -/path/to/directory
  
  expression_string.slice!( 0, 1 )
  path_string = expression_string.dup
  expression_string.clear

  @general_load_paths.delete( ::File.expand_path( path_string ) )
  
  return self
  
end

.require(gem_name_or_path) ⇒ true, false

Filters requires to match configuration specifications for loading development paths instead of production gems.

Parameters:

Returns:

  • (true, false)

    Whether Development handled gem_name_or_path (true) or processing should continue (false).



863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
# File 'lib/development.rb', line 863

def self.require( gem_name_or_path )
  
  did_load = false

  # if our path ends with an extension we are not requiring a gem and thus not responsible for managing it
  if ::File.extname( gem_name_or_path ).empty?

    gem_name = gem_name_or_path.to_s
    
    # ensure we have 'gem-subname' rather than 'gem/subname'
    # we really just need one or the other consistently
    gem_directory_name = gem_name.gsub( '/', '-' )
    
    # look for gem name in enabled gems/gemsets
    if @enabled_gems.include?( gem_name.to_sym ) or 
       @enable_for_all && ! @disabled_gems.include?( gem_name.to_sym )

      if directory_name = @gem_locations[ gem_name.to_sym ]   and
         load_path = directory( directory_name )              and
         gem_name_at_load_path?( load_path, gem_directory_name, true )
        
        load_gem_from_path( load_path, gem_directory_name )
        did_load = true
        
      else
        # look in each path for gem - use first to match
        @general_load_paths.each do |this_load_path|

          # look for gem name at load path
          if gem_name_at_load_path?( this_load_path, gem_name )
            load_gem_from_path( this_load_path, gem_name )
            did_load = true
          end

        end
      
      end
  
    end

  end
  
  return did_load
  
end

Instance Method Details

#loaded?(gem_name) ⇒ true, false

Query whether gem was loaded via Development rather than standard require.

Parameters:

  • gem_name

    Name of gem.

Returns:

  • (true, false)

    Whether gem was loaded via Development.



22
23
24
25
26
# File 'lib/development.rb', line 22

def loaded?( gem_name )
  
  return @loaded_gems.include?( gem_name )
  
end