@@ -35,7 +35,6 @@ def initialize(diagnostics_producer)
35
35
36
36
@check_visitor = self . class . check_visitor
37
37
@acceptor = diagnostics_producer
38
- @file_to_namespace = { }
39
38
40
39
# Use null migration checker unless given in context
41
40
@migration_checker = ( Puppet . lookup ( :migration_checker ) { Migration ::MigrationChecker . new ( ) } )
@@ -533,75 +532,103 @@ def internal_check_future_reserved_word(o, name)
533
532
end
534
533
end
535
534
535
+ NO_NAMESPACE = :no_namespace
536
+ NO_PATH = :no_path
537
+ BAD_MODULE_FILE = :bad_module_file
536
538
def internal_check_file_namespace ( o , name , file )
537
- return if file . nil?
539
+ return if file . nil? || file == '' #e.g. puppet apply -e '...'
538
540
539
- lc_file = file . downcase
541
+ file_namespace = namespace_for_file ( file )
542
+ return if file_namespace == NO_NAMESPACE
540
543
541
- file_namespace = @file_to_namespace [ lc_file ]
542
- if file_namespace . nil?
543
- return if @file_to_namespace . key? ( lc_file )
544
- file_namespace = @file_to_namespace [ lc_file ] = namespace_for_file ( lc_file )
545
- return if file_namespace . nil?
546
- end
547
-
548
- if !name . downcase . start_with? ( file_namespace )
544
+ # Downcasing here because check is case-insensitive
545
+ if file_namespace == BAD_MODULE_FILE || !name . downcase . start_with? ( file_namespace )
549
546
acceptor . accept ( Issues ::ILLEGAL_DEFINITION_LOCATION , o , { :name => name , :file => file } )
550
547
end
551
548
end
552
549
553
- NEVER_MATCH = '\b' . freeze
550
+ # @api private
551
+ class Puppet ::Util ::FileNamespaceAdapter < Puppet ::Pops ::Adaptable ::Adapter
552
+ attr_accessor :file_to_namespace
553
+ end
554
554
555
555
def namespace_for_file ( file )
556
- path = Pathname . new ( file )
556
+ env = Puppet . lookup ( :current_environment )
557
+ return NO_NAMESPACE if env . nil?
557
558
558
- return nil if path . extname != ".pp"
559
+ Puppet ::Util ::FileNamespaceAdapter . adapt ( env ) do |adapter |
560
+ adapter . file_to_namespace ||= { }
559
561
560
- return nil if initial_manifest? ( path )
562
+ file_namespace = adapter . file_to_namespace [ file ]
563
+ return file_namespace unless file_namespace . nil? # No cache entry, so we do the calculation
561
564
562
- path = path . each_filename . to_a
565
+ path = Pathname . new ( file )
563
566
564
- # Example definition dir: manifests in this path:
565
- # <modules dir>/<module name>/manifests/<module subdir>/<classfile>.pp
566
- definition_dir_index = find_module_definition_dir ( path )
567
+ return adapter . file_to_namespace [ file ] = NO_NAMESPACE if path . extname != ".pp"
567
568
568
- # How can we get this result?
569
- # If it is not an initial manifest, it must come from a module,
570
- # and from the manifests dir there. This may never get used...
571
- return NEVER_MATCH if definition_dir_index . nil? || definition_dir_index == 0
569
+ path = path . expand_path
572
570
573
- before_definition_dir = definition_dir_index - 1
574
- after_definition_dir = definition_dir_index + 1
575
- names = path [ after_definition_dir .. -2 ] # Directories inside module
576
- names . unshift ( path [ before_definition_dir ] ) # Name of the module itself
577
- # Do not include name of module init file at top level of module
578
- filename = path [ -1 ]
579
- if !( path . length == ( after_definition_dir +1 ) && filename == 'init.pp' )
580
- names . push ( filename [ 0 .. -4 ] ) # Remove .pp from filename
571
+ return adapter . file_to_namespace [ file ] = NO_NAMESPACE if initial_manifest? ( path , env . manifest )
572
+
573
+ #All auto-loaded files from modules come from a module search path dir
574
+ relative_path = get_module_relative_path ( path , env . full_modulepath )
575
+
576
+ return adapter . file_to_namespace [ file ] = NO_NAMESPACE if relative_path == NO_PATH
577
+
578
+ #If a file comes from a module, but isn't in the right place, always error
579
+ names = dir_to_names ( relative_path )
580
+
581
+ return adapter . file_to_namespace [ file ] = ( names == BAD_MODULE_FILE ? BAD_MODULE_FILE : names . join ( "::" ) . freeze )
581
582
end
583
+ end
584
+
585
+ def initial_manifest? ( path , manifest_setting )
586
+ return false if manifest_setting . nil? || manifest_setting == :no_manifest
582
587
583
- names . join ( "::" ) . freeze
588
+ string_path = path . to_s
589
+
590
+ string_path == manifest_setting || string_path . start_with? ( manifest_setting )
584
591
end
585
592
586
- def initial_manifest? ( path )
587
- manifest_setting = Puppet [ :manifest ]
593
+ def get_module_relative_path ( file_path , modulepath_directories )
594
+ clean_file = file_path . cleanpath
595
+ parent_path = modulepath_directories . find { |path_dir | is_parent_dir_of ( path_dir , clean_file ) }
596
+ return NO_PATH if parent_path . nil?
588
597
589
- # Does this ever happen outside of tests?
590
- if manifest_setting . nil?
591
- return path . basename . to_s == 'site.pp'
592
- end
598
+ file_path . relative_path_from ( Pathname . new ( parent_path ) )
599
+ end
600
+
601
+ def is_parent_dir_of ( parent_dir , child_dir )
602
+ parent_dir_path = Pathname . new ( parent_dir )
603
+ clean_parent = parent_dir_path . cleanpath
593
604
594
- full_path = path . expand_path . to_s
595
- full_path == manifest_setting || full_path . start_with? ( manifest_setting )
605
+ return child_dir . to_s . start_with? ( clean_parent . to_s )
596
606
end
597
607
598
- # Returns module root directory index in path for files under 'manifests',
599
- # 'functions', 'types' and 'plans'
600
- def find_module_definition_dir ( path )
601
- reverse_index = path . reverse_each . find_index do |dir |
602
- dir == 'manifests' || dir == 'functions' || dir == 'types' || dir == 'plans'
608
+ def dir_to_names ( relative_path )
609
+ # Downcasing here because check is case-insensitive
610
+ path_components = relative_path . to_s . downcase . split ( File ::SEPARATOR )
611
+
612
+ # Example definition dir: manifests in this path:
613
+ # <module name>/manifests/<module subdir>/<classfile>.pp
614
+ dir = path_components [ 1 ]
615
+
616
+ # How can we get this result?
617
+ # If it is not an initial manifest, it must come from a module,
618
+ # and from the manifests dir there. This may never get used...
619
+ return BAD_MODULE_FILE unless dir == 'manifests' || dir == 'functions' || dir == 'types' || dir == 'plans'
620
+
621
+ names = path_components [ 2 .. -2 ] # Directories inside module
622
+ names . unshift ( path_components [ 0 ] ) # Name of the module itself
623
+
624
+ # Do not include name of module init file at top level of module
625
+ # e.g. <module name>/manifests/init.pp
626
+ filename = path_components [ -1 ]
627
+ if !( path_components . length == 3 && filename == 'init.pp' )
628
+ names . push ( filename [ 0 .. -4 ] ) # Remove .pp from filename
603
629
end
604
- return reverse_index . nil? ? nil : ( path . length - 1 ) - reverse_index
630
+
631
+ names
605
632
end
606
633
607
634
RESERVED_PARAMETERS = {
0 commit comments