delfos 0.0.1.pre.rc1 → 0.0.1
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.
- checksums.yaml +4 -4
 - data/lib/delfos.rb +22 -78
 - data/lib/delfos/call_stack.rb +39 -0
 - data/lib/delfos/call_stack/stack.rb +59 -0
 - data/lib/delfos/file_system/common_path.rb +62 -0
 - data/lib/delfos/{distance/calculation.rb → file_system/distance_calculation.rb} +4 -15
 - data/lib/delfos/file_system/path_determination.rb +37 -0
 - data/lib/delfos/{distance → file_system}/relation.rb +1 -1
 - data/lib/delfos/method_logging.rb +32 -49
 - data/lib/delfos/method_logging/call_site_parsing.rb +74 -0
 - data/lib/delfos/method_logging/code_location.rb +34 -98
 - data/lib/delfos/method_logging/{args.rb → method_parameters.rb} +17 -18
 - data/lib/delfos/neo4j.rb +58 -0
 - data/lib/delfos/neo4j/batch/execution.rb +149 -0
 - data/lib/delfos/neo4j/{execution_persistence.rb → call_stack_query.rb} +12 -22
 - data/lib/delfos/neo4j/distance/call_site_fetcher.rb +19 -0
 - data/lib/delfos/neo4j/distance/update.rb +50 -0
 - data/lib/delfos/neo4j/informer.rb +62 -34
 - data/lib/delfos/neo4j/query_execution/errors.rb +30 -0
 - data/lib/delfos/neo4j/query_execution/http.rb +61 -0
 - data/lib/delfos/neo4j/query_execution/http_query.rb +67 -0
 - data/lib/delfos/neo4j/query_execution/sync.rb +35 -0
 - data/lib/delfos/neo4j/query_execution/transactional.rb +68 -0
 - data/lib/delfos/neo4j/schema.rb +73 -0
 - data/lib/delfos/patching/basic_object.rb +1 -5
 - data/lib/delfos/patching/method_cache.rb +83 -0
 - data/lib/delfos/patching/method_override.rb +76 -66
 - data/lib/delfos/patching/module_defining_methods.rb +105 -0
 - data/lib/delfos/patching/unstubber.rb +34 -0
 - data/lib/delfos/setup.rb +88 -0
 - metadata +42 -15
 - data/lib/delfos/common_path.rb +0 -58
 - data/lib/delfos/execution_chain.rb +0 -75
 - data/lib/delfos/method_logging/added_methods.rb +0 -67
 - data/lib/delfos/neo4j/distance_update.rb +0 -73
 - data/lib/delfos/neo4j/query_execution.rb +0 -79
 - data/lib/delfos/patching/unstubbing_spec_helper.rb +0 -58
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA1:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 87475ed3a25d014e199e651988f4d3183561816a
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 0c2441e45f0dfbe6b272e0904654907fba9f53d2
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 84f4de34ff44908ce8794643553ece54cd9914cc519502d3bfb3adfc3caa0e97effbefa65aba573f1ade386839798c496bd7adf10822ff9ff3c9734459ec1bcc
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 9fd34ca930e93e73a5e16294a6fc4a94464accd3f8b91353a9a8c94d99a418ef7494855b79f064334ed102a70107a9049f3e1e554f37e4c88e5681392cd7d85d
         
     | 
    
        data/lib/delfos.rb
    CHANGED
    
    | 
         @@ -1,100 +1,44 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
     | 
    
         
            -
            require "delfos/ 
     | 
| 
      
 2 
     | 
    
         
            +
            require "delfos/setup"
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
            module Delfos
         
     | 
| 
       5 
5 
     | 
    
         
             
              class << self
         
     | 
| 
       6 
     | 
    
         
            -
                 
     | 
| 
      
 6 
     | 
    
         
            +
                attr_accessor :application_directories
         
     | 
| 
      
 7 
     | 
    
         
            +
                attr_writer :logger, :neo4j
         
     | 
| 
       7 
8 
     | 
    
         | 
| 
       8 
     | 
    
         
            -
                def  
     | 
| 
       9 
     | 
    
         
            -
                   
     | 
| 
      
 9 
     | 
    
         
            +
                def setup!(logger: nil, call_site_logger: nil, application_directories: nil)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  self.logger = logger if logger
         
     | 
| 
      
 11 
     | 
    
         
            +
                  Delfos::Setup.perform!(call_site_logger: call_site_logger, application_directories: application_directories)
         
     | 
| 
       10 
12 
     | 
    
         
             
                end
         
     | 
| 
       11 
13 
     | 
    
         | 
| 
       12 
     | 
    
         
            -
                def  
     | 
| 
       13 
     | 
    
         
            -
                  Delfos. 
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
                  require "delfos/neo4j/query_execution"
         
     | 
| 
       16 
     | 
    
         
            -
                  Delfos::Neo4j::QueryExecution.execute <<-QUERY
         
     | 
| 
       17 
     | 
    
         
            -
                    MATCH (m)-[rel]->(n)
         
     | 
| 
       18 
     | 
    
         
            -
                    DELETE m,rel,n
         
     | 
| 
       19 
     | 
    
         
            -
                  QUERY
         
     | 
| 
      
 14 
     | 
    
         
            +
                def call_site_logger
         
     | 
| 
      
 15 
     | 
    
         
            +
                  Delfos::Setup.call_site_logger
         
     | 
| 
       20 
16 
     | 
    
         
             
                end
         
     | 
| 
       21 
17 
     | 
    
         | 
| 
       22 
     | 
    
         
            -
                def  
     | 
| 
       23 
     | 
    
         
            -
                   
     | 
| 
       24 
     | 
    
         
            -
                  @method_logging = nil
         
     | 
| 
       25 
     | 
    
         
            -
                  @neo4j = nil
         
     | 
| 
       26 
     | 
    
         
            -
                  @logger = nil
         
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
                  if defined? Delfos::ExecutionChain
         
     | 
| 
       29 
     | 
    
         
            -
                    Delfos::ExecutionChain.reset!
         
     | 
| 
       30 
     | 
    
         
            -
                  end
         
     | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
     | 
    
         
            -
                  # unstubbing depends upon AddedMethods being still defined
         
     | 
| 
       33 
     | 
    
         
            -
                  # so this order is important
         
     | 
| 
       34 
     | 
    
         
            -
                  unstub_all!
         
     | 
| 
       35 
     | 
    
         
            -
                  remove_added_methods!
         
     | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
       37 
     | 
    
         
            -
                  remove_patching!
         
     | 
| 
      
 18 
     | 
    
         
            +
                def call_site_logger=(call_site_logger)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  Delfos::Setup.call_site_logger = call_site_logger
         
     | 
| 
       38 
20 
     | 
    
         
             
                end
         
     | 
| 
       39 
21 
     | 
    
         | 
| 
       40 
     | 
    
         
            -
                def  
     | 
| 
       41 
     | 
    
         
            -
                   
     | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
       43 
     | 
    
         
            -
                    if Delfos::Patching::MethodOverride.respond_to?(:unstub_all!)
         
     | 
| 
       44 
     | 
    
         
            -
                      Delfos::Patching::MethodOverride.unstub_all!
         
     | 
| 
       45 
     | 
    
         
            -
                    end
         
     | 
| 
       46 
     | 
    
         
            -
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
                def logger
         
     | 
| 
      
 23 
     | 
    
         
            +
                  @logger ||= default_logger
         
     | 
| 
       47 
24 
     | 
    
         
             
                end
         
     | 
| 
       48 
25 
     | 
    
         | 
| 
       49 
     | 
    
         
            -
                def  
     | 
| 
       50 
     | 
    
         
            -
                   
     | 
| 
       51 
     | 
    
         
            -
                    Delfos::MethodLogging::AddedMethods.instance_eval { @instance = nil }
         
     | 
| 
       52 
     | 
    
         
            -
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
                def neo4j
         
     | 
| 
      
 27 
     | 
    
         
            +
                  setup_neo4j!
         
     | 
| 
       53 
28 
     | 
    
         
             
                end
         
     | 
| 
       54 
29 
     | 
    
         | 
| 
       55 
     | 
    
         
            -
                def  
     | 
| 
       56 
     | 
    
         
            -
                   
     | 
| 
      
 30 
     | 
    
         
            +
                def setup_neo4j!
         
     | 
| 
      
 31 
     | 
    
         
            +
                  require "delfos/neo4j"
         
     | 
| 
      
 32 
     | 
    
         
            +
                  @neo4j ||= Delfos::Neo4j.config
         
     | 
| 
       57 
33 
     | 
    
         
             
                end
         
     | 
| 
       58 
34 
     | 
    
         | 
| 
       59 
     | 
    
         
            -
                def  
     | 
| 
       60 
     | 
    
         
            -
             
     | 
| 
       61 
     | 
    
         
            -
                           neo4j_username: nil,
         
     | 
| 
       62 
     | 
    
         
            -
                           neo4j_password: nil,
         
     | 
| 
       63 
     | 
    
         
            -
                           application_directories: nil)
         
     | 
| 
       64 
     | 
    
         
            -
                  application_directories ||= %w(app lib)
         
     | 
| 
       65 
     | 
    
         
            -
             
     | 
| 
       66 
     | 
    
         
            -
                  @application_directories = if application_directories.is_a?(Proc)
         
     | 
| 
       67 
     | 
    
         
            -
                                               application_directories
         
     | 
| 
       68 
     | 
    
         
            -
                                             else
         
     | 
| 
       69 
     | 
    
         
            -
                                               Array(application_directories).map { |f| Pathname.new(File.expand_path(f.to_s)) }
         
     | 
| 
       70 
     | 
    
         
            -
                                             end
         
     | 
| 
       71 
     | 
    
         
            -
             
     | 
| 
       72 
     | 
    
         
            -
                  @logger = logger
         
     | 
| 
       73 
     | 
    
         
            -
             
     | 
| 
       74 
     | 
    
         
            -
                  setup_neo4j!(neo4j_url, neo4j_username, neo4j_password)
         
     | 
| 
       75 
     | 
    
         
            -
             
     | 
| 
       76 
     | 
    
         
            -
                  perform_patching!
         
     | 
| 
       77 
     | 
    
         
            -
                end
         
     | 
| 
       78 
     | 
    
         
            -
             
     | 
| 
       79 
     | 
    
         
            -
                def setup_neo4j!(url = nil, username = nil, password = nil)
         
     | 
| 
       80 
     | 
    
         
            -
                  url ||= ENV["NEO4J_URL"] || "http://localhost:7474"
         
     | 
| 
       81 
     | 
    
         
            -
                  username ||= ENV["NEO4J_USERNAME"] || "neo4j"
         
     | 
| 
       82 
     | 
    
         
            -
                  password ||= ENV["NEO4J_PASSWORD"] || "password"
         
     | 
| 
       83 
     | 
    
         
            -
                  @neo4j = Neo4jOptions.new(url, username, password)
         
     | 
| 
       84 
     | 
    
         
            -
                end
         
     | 
| 
       85 
     | 
    
         
            -
             
     | 
| 
       86 
     | 
    
         
            -
                def perform_patching!
         
     | 
| 
       87 
     | 
    
         
            -
                  load "delfos/patching/basic_object.rb"
         
     | 
| 
      
 35 
     | 
    
         
            +
                def reset!
         
     | 
| 
      
 36 
     | 
    
         
            +
                  Delfos::Setup.reset!
         
     | 
| 
       88 
37 
     | 
    
         
             
                end
         
     | 
| 
       89 
38 
     | 
    
         | 
| 
       90 
     | 
    
         
            -
                 
     | 
| 
       91 
     | 
    
         
            -
             
     | 
| 
       92 
     | 
    
         
            -
             
     | 
| 
       93 
     | 
    
         
            -
                  def to_s
         
     | 
| 
       94 
     | 
    
         
            -
                    "  url: #{url}\n  username: #{username}\n  password: #{password}"
         
     | 
| 
       95 
     | 
    
         
            -
                  end
         
     | 
| 
      
 39 
     | 
    
         
            +
                def default_logger
         
     | 
| 
      
 40 
     | 
    
         
            +
                  require "logger"
         
     | 
| 
      
 41 
     | 
    
         
            +
                  Logger.new(STDOUT)
         
     | 
| 
       96 
42 
     | 
    
         
             
                end
         
     | 
| 
       97 
     | 
    
         
            -
             
     | 
| 
       98 
     | 
    
         
            -
                attr_reader :application_directories, :neo4j_host, :neo4j_username, :neo4j_password
         
     | 
| 
       99 
43 
     | 
    
         
             
              end
         
     | 
| 
       100 
44 
     | 
    
         
             
            end
         
     | 
| 
         @@ -0,0 +1,39 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
            require_relative "neo4j"
         
     | 
| 
      
 3 
     | 
    
         
            +
            require_relative "neo4j/call_stack_query"
         
     | 
| 
      
 4 
     | 
    
         
            +
            require_relative "call_stack/stack"
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module Delfos
         
     | 
| 
      
 7 
     | 
    
         
            +
              module CallStack
         
     | 
| 
      
 8 
     | 
    
         
            +
                CALL_STACK_MUTEX = Mutex.new
         
     | 
| 
      
 9 
     | 
    
         
            +
                extend self
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                def reset!
         
     | 
| 
      
 12 
     | 
    
         
            +
                  CALL_STACK_MUTEX.synchronize do
         
     | 
| 
      
 13 
     | 
    
         
            +
                    Thread.current[:_delfos__call_stack] = nil
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                def stack
         
     | 
| 
      
 18 
     | 
    
         
            +
                  CALL_STACK_MUTEX.synchronize do
         
     | 
| 
      
 19 
     | 
    
         
            +
                    Thread.current[:_delfos__call_stack] ||= Stack.new(on_empty: method(:save!))
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                def push(method_object)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  stack.push(method_object)
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                def pop
         
     | 
| 
      
 28 
     | 
    
         
            +
                  stack.pop
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                def pop_until_top!
         
     | 
| 
      
 32 
     | 
    
         
            +
                  stack.pop_until_top!
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                def save!(call_sites, execution_number)
         
     | 
| 
      
 36 
     | 
    
         
            +
                  Delfos::MethodLogging.save_call_stack(call_sites, execution_number)
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
              end
         
     | 
| 
      
 39 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,59 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
            module Delfos
         
     | 
| 
      
 3 
     | 
    
         
            +
              module CallStack
         
     | 
| 
      
 4 
     | 
    
         
            +
                class Stack
         
     | 
| 
      
 5 
     | 
    
         
            +
                  def initialize(on_empty: nil)
         
     | 
| 
      
 6 
     | 
    
         
            +
                    @on_empty = on_empty
         
     | 
| 
      
 7 
     | 
    
         
            +
                  end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  def push(method_object)
         
     | 
| 
      
 10 
     | 
    
         
            +
                    call_sites.push(method_object)
         
     | 
| 
      
 11 
     | 
    
         
            +
                    self.stack_depth += 1
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                    self.execution_count += self.stack_depth == 1 ? 1 : 0
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  def pop
         
     | 
| 
      
 17 
     | 
    
         
            +
                    popping_empty_stack! if self.stack_depth.zero?
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                    self.stack_depth -= 1
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                    if stack_depth.zero? && call_sites.length.positive?
         
     | 
| 
      
 22 
     | 
    
         
            +
                      @on_empty&.call(call_sites, execution_count)
         
     | 
| 
      
 23 
     | 
    
         
            +
                      self.call_sites = []
         
     | 
| 
      
 24 
     | 
    
         
            +
                    end
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  def pop_until_top!
         
     | 
| 
      
 28 
     | 
    
         
            +
                    pop while self.stack_depth.positive?
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  def stack_depth
         
     | 
| 
      
 32 
     | 
    
         
            +
                    @stack_depth ||= 0
         
     | 
| 
      
 33 
     | 
    
         
            +
                  end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                  def execution_count
         
     | 
| 
      
 36 
     | 
    
         
            +
                    @execution_count ||= 0
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                  def call_sites
         
     | 
| 
      
 40 
     | 
    
         
            +
                    @call_sites ||= []
         
     | 
| 
      
 41 
     | 
    
         
            +
                  end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                  def step_count
         
     | 
| 
      
 44 
     | 
    
         
            +
                    call_sites.length
         
     | 
| 
      
 45 
     | 
    
         
            +
                  end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                  attr_writer :stack_depth, :step_count, :execution_count, :call_sites
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                  private
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                  def popping_empty_stack!
         
     | 
| 
      
 52 
     | 
    
         
            +
                    raise PoppingEmptyStackError
         
     | 
| 
      
 53 
     | 
    
         
            +
                  end
         
     | 
| 
      
 54 
     | 
    
         
            +
                end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                class PoppingEmptyStackError < StandardError
         
     | 
| 
      
 57 
     | 
    
         
            +
                end
         
     | 
| 
      
 58 
     | 
    
         
            +
              end
         
     | 
| 
      
 59 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,62 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
            require "pathname"
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module Delfos
         
     | 
| 
      
 5 
     | 
    
         
            +
              module FileSystem
         
     | 
| 
      
 6 
     | 
    
         
            +
                module CommonPath
         
     | 
| 
      
 7 
     | 
    
         
            +
                  class << self
         
     | 
| 
      
 8 
     | 
    
         
            +
                    SEPARATOR = "/"
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                    def included_in?(p1, paths)
         
     | 
| 
      
 11 
     | 
    
         
            +
                      paths.any? do |p2|
         
     | 
| 
      
 12 
     | 
    
         
            +
                        common = common_parent(p1, p2)
         
     | 
| 
      
 13 
     | 
    
         
            +
                        common.to_s.length >= p2.to_s.length
         
     | 
| 
      
 14 
     | 
    
         
            +
                      end
         
     | 
| 
      
 15 
     | 
    
         
            +
                    end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                    def common_parent(path_a, path_b)
         
     | 
| 
      
 18 
     | 
    
         
            +
                      dirs = [
         
     | 
| 
      
 19 
     | 
    
         
            +
                        File.expand_path(path_a.to_s),
         
     | 
| 
      
 20 
     | 
    
         
            +
                        File.expand_path(path_b.to_s),
         
     | 
| 
      
 21 
     | 
    
         
            +
                      ]
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                      dir1, dir2 = dirs.minmax.map { |dir| dir.split(SEPARATOR) }
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                      path_from(dir1, dir2, path_a, path_b)
         
     | 
| 
      
 26 
     | 
    
         
            +
                    end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                    private
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                    def path_from(dir1, dir2, path_a, path_b)
         
     | 
| 
      
 31 
     | 
    
         
            +
                      common_path = common_path(dir1, dir2)
         
     | 
| 
      
 32 
     | 
    
         
            +
                      common_path, path_a, path_b = append_trailing_slashes!(common_path, path_a, path_b)
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                      Pathname.new(common_path) if valid_length?(common_path, path_a, path_b)
         
     | 
| 
      
 35 
     | 
    
         
            +
                    end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                    def valid_length?(common_path, path_a, path_b)
         
     | 
| 
      
 38 
     | 
    
         
            +
                      l = common_path.to_s.length
         
     | 
| 
      
 39 
     | 
    
         
            +
                      (l <= path_a.to_s.length) || (l <= path_b.to_s.length)
         
     | 
| 
      
 40 
     | 
    
         
            +
                    end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                    def common_path(dir1, dir2)
         
     | 
| 
      
 43 
     | 
    
         
            +
                      dir1.
         
     | 
| 
      
 44 
     | 
    
         
            +
                        zip(dir2).
         
     | 
| 
      
 45 
     | 
    
         
            +
                        take_while { |dn1, dn2| dn1 == dn2 }.
         
     | 
| 
      
 46 
     | 
    
         
            +
                        map(&:first).
         
     | 
| 
      
 47 
     | 
    
         
            +
                        join(SEPARATOR)
         
     | 
| 
      
 48 
     | 
    
         
            +
                    end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                    def append_trailing_slashes!(*paths)
         
     | 
| 
      
 51 
     | 
    
         
            +
                      paths.map do |path|
         
     | 
| 
      
 52 
     | 
    
         
            +
                        if Pathname.new(path).directory?
         
     | 
| 
      
 53 
     | 
    
         
            +
                          path += SEPARATOR if path && path.to_s[-1] != SEPARATOR
         
     | 
| 
      
 54 
     | 
    
         
            +
                        end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                        path
         
     | 
| 
      
 57 
     | 
    
         
            +
                      end
         
     | 
| 
      
 58 
     | 
    
         
            +
                    end
         
     | 
| 
      
 59 
     | 
    
         
            +
                  end
         
     | 
| 
      
 60 
     | 
    
         
            +
                end
         
     | 
| 
      
 61 
     | 
    
         
            +
              end
         
     | 
| 
      
 62 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -1,14 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         
             
            require_relative "relation"
         
     | 
| 
      
 3 
     | 
    
         
            +
            require_relative "path_determination"
         
     | 
| 
       3 
4 
     | 
    
         | 
| 
       4 
5 
     | 
    
         
             
            module Delfos
         
     | 
| 
       5 
     | 
    
         
            -
              module  
     | 
| 
       6 
     | 
    
         
            -
                class  
     | 
| 
      
 6 
     | 
    
         
            +
              module FileSystem
         
     | 
| 
      
 7 
     | 
    
         
            +
                class DistanceCalculation
         
     | 
| 
       7 
8 
     | 
    
         
             
                  attr_reader :path_a, :path_b
         
     | 
| 
       8 
9 
     | 
    
         | 
| 
       9 
10 
     | 
    
         
             
                  def initialize(path_a, path_b)
         
     | 
| 
       10 
     | 
    
         
            -
                    @path_a = path_a
         
     | 
| 
       11 
     | 
    
         
            -
                    @path_b = path_b
         
     | 
| 
      
 11 
     | 
    
         
            +
                    @path_a, @path_b = PathDetermination.for(path_a, path_b)
         
     | 
| 
       12 
12 
     | 
    
         
             
                  end
         
     | 
| 
       13 
13 
     | 
    
         | 
| 
       14 
14 
     | 
    
         
             
                  attr_reader :traversal_a, :traversal_b
         
     | 
| 
         @@ -42,17 +42,6 @@ module Delfos 
     | 
|
| 
       42 
42 
     | 
    
         
             
                    siblings(path).select { |f| File.directory?(f) }
         
     | 
| 
       43 
43 
     | 
    
         
             
                  end
         
     | 
| 
       44 
44 
     | 
    
         | 
| 
       45 
     | 
    
         
            -
                  def in_start_directory?(path)
         
     | 
| 
       46 
     | 
    
         
            -
                    return false if path.directory?
         
     | 
| 
       47 
     | 
    
         
            -
                    path_a.dirname == path
         
     | 
| 
       48 
     | 
    
         
            -
                  end
         
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
       50 
     | 
    
         
            -
                  def in_finish_directory?(path)
         
     | 
| 
       51 
     | 
    
         
            -
                    return false if path.directory?
         
     | 
| 
       52 
     | 
    
         
            -
             
     | 
| 
       53 
     | 
    
         
            -
                    path_b.dirname == path
         
     | 
| 
       54 
     | 
    
         
            -
                  end
         
     | 
| 
       55 
     | 
    
         
            -
             
     | 
| 
       56 
45 
     | 
    
         
             
                  def traversal_path
         
     | 
| 
       57 
46 
     | 
    
         
             
                    TraversalPathCalculator.new(path_a, path_b).path
         
     | 
| 
       58 
47 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -0,0 +1,37 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
            module Delfos
         
     | 
| 
      
 3 
     | 
    
         
            +
              module FileSystem
         
     | 
| 
      
 4 
     | 
    
         
            +
                class PathDetermination
         
     | 
| 
      
 5 
     | 
    
         
            +
                  def self.for(*files)
         
     | 
| 
      
 6 
     | 
    
         
            +
                    files.map { |f| new(f).full_path }
         
     | 
| 
      
 7 
     | 
    
         
            +
                  end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  def initialize(file)
         
     | 
| 
      
 10 
     | 
    
         
            +
                    @file = Pathname.new(strip_block_message(file))
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  def full_path
         
     | 
| 
      
 14 
     | 
    
         
            +
                    return @file.realpath if File.exist?(@file)
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                    Delfos.application_directories.map do |d|
         
     | 
| 
      
 17 
     | 
    
         
            +
                      path = try_path { d + @file }
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                      path || try_path do
         
     | 
| 
      
 20 
     | 
    
         
            +
                        Pathname.new(d + @file.to_s.gsub(%r{[^/]*/}, ""))
         
     | 
| 
      
 21 
     | 
    
         
            +
                      end
         
     | 
| 
      
 22 
     | 
    
         
            +
                    end.compact.first
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  private
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  def strip_block_message(f)
         
     | 
| 
      
 28 
     | 
    
         
            +
                    f.to_s.split(" in block").first
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  def try_path
         
     | 
| 
      
 32 
     | 
    
         
            +
                    path = yield
         
     | 
| 
      
 33 
     | 
    
         
            +
                    path if path.exist?
         
     | 
| 
      
 34 
     | 
    
         
            +
                  end
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -1,69 +1,52 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
     | 
    
         
            -
            require " 
     | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
       4 
     | 
    
         
            -
            require "binding_of_caller"
         
     | 
| 
       5 
     | 
    
         
            -
            require_relative "common_path"
         
     | 
| 
      
 2 
     | 
    
         
            +
            require "delfos/file_system/common_path"
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
       6 
4 
     | 
    
         
             
            require_relative "method_logging/code_location"
         
     | 
| 
       7 
     | 
    
         
            -
            require_relative "method_logging/ 
     | 
| 
       8 
     | 
    
         
            -
            require_relative "execution_chain"
         
     | 
| 
      
 5 
     | 
    
         
            +
            require_relative "method_logging/method_parameters"
         
     | 
| 
       9 
6 
     | 
    
         | 
| 
       10 
7 
     | 
    
         
             
            module Delfos
         
     | 
| 
       11 
     | 
    
         
            -
               
     | 
| 
       12 
     | 
    
         
            -
                 
     | 
| 
       13 
     | 
    
         
            -
                attr_writer :method_logging
         
     | 
| 
      
 8 
     | 
    
         
            +
              module MethodLogging
         
     | 
| 
      
 9 
     | 
    
         
            +
                extend self
         
     | 
| 
       14 
10 
     | 
    
         | 
| 
       15 
     | 
    
         
            -
                def  
     | 
| 
       16 
     | 
    
         
            -
                   
     | 
| 
      
 11 
     | 
    
         
            +
                def save_call_stack(call_sites, execution_number)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  Delfos.call_site_logger.save_call_stack(call_sites, execution_number)
         
     | 
| 
       17 
13 
     | 
    
         
             
                end
         
     | 
| 
       18 
     | 
    
         
            -
              end
         
     | 
| 
       19 
14 
     | 
    
         | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
      
 15 
     | 
    
         
            +
                def log(call_site, called_object, called_method, class_method, parameters)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  called_code = CodeLocation.from_called(called_object, called_method, class_method)
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  Delfos.call_site_logger.log(parameters, call_site, called_code)
         
     | 
| 
       23 
19 
     | 
    
         
             
                end
         
     | 
| 
       24 
     | 
    
         
            -
              end
         
     | 
| 
       25 
20 
     | 
    
         | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
                   
     | 
| 
       29 
     | 
    
         
            -
                    raise Delfos::ApplicationDirectoriesNotDefined unless Delfos.application_directories
         
     | 
| 
       30 
     | 
    
         
            -
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
                def exclude?(method)
         
     | 
| 
      
 22 
     | 
    
         
            +
                  file, = method.source_location
         
     | 
| 
      
 23 
     | 
    
         
            +
                  return true unless file
         
     | 
| 
       31 
24 
     | 
    
         | 
| 
       32 
     | 
    
         
            -
                   
     | 
| 
       33 
     | 
    
         
            -
             
     | 
| 
       34 
     | 
    
         
            -
                    arguments = Args.new(arguments)
         
     | 
| 
       35 
     | 
    
         
            -
                    called_code = CodeLocation.from_called(called_object, called_method, class_method)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  exclude_file?(File.expand_path(file))
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
       36 
27 
     | 
    
         | 
| 
       37 
     | 
    
         
            -
             
     | 
| 
       38 
     | 
    
         
            -
                   
     | 
| 
      
 28 
     | 
    
         
            +
                def include_file?(file)
         
     | 
| 
      
 29 
     | 
    
         
            +
                  !exclude_file?(file)
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
       39 
31 
     | 
    
         | 
| 
       40 
     | 
    
         
            -
             
     | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
       43 
     | 
    
         
            -
                    end
         
     | 
| 
      
 32 
     | 
    
         
            +
                def exclude_file?(file)
         
     | 
| 
      
 33 
     | 
    
         
            +
                  with_cache(file) do
         
     | 
| 
      
 34 
     | 
    
         
            +
                    !FileSystem::CommonPath.included_in?(File.expand_path(file), Delfos.application_directories)
         
     | 
| 
       44 
35 
     | 
    
         
             
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
       45 
37 
     | 
    
         | 
| 
       46 
     | 
    
         
            -
             
     | 
| 
       47 
     | 
    
         
            -
             
     | 
| 
       48 
     | 
    
         
            -
             
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
       50 
     | 
    
         
            -
                    exclude_file_from_logging?(File.expand_path(file))
         
     | 
| 
       51 
     | 
    
         
            -
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
                def reset!
         
     | 
| 
      
 39 
     | 
    
         
            +
                  @cache = nil
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
       52 
41 
     | 
    
         | 
| 
       53 
     | 
    
         
            -
             
     | 
| 
       54 
     | 
    
         
            -
                    !exclude_file_from_logging?(file)
         
     | 
| 
       55 
     | 
    
         
            -
                  end
         
     | 
| 
      
 42 
     | 
    
         
            +
                private
         
     | 
| 
       56 
43 
     | 
    
         | 
| 
       57 
     | 
    
         
            -
             
     | 
| 
       58 
     | 
    
         
            -
             
     | 
| 
       59 
     | 
    
         
            -
             
     | 
| 
      
 44 
     | 
    
         
            +
                def with_cache(key)
         
     | 
| 
      
 45 
     | 
    
         
            +
                  cache.include?(key) ? cache[key] : cache[key] = yield
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
       60 
47 
     | 
    
         | 
| 
       61 
     | 
    
         
            -
             
     | 
| 
       62 
     | 
    
         
            -
             
     | 
| 
       63 
     | 
    
         
            -
                    else
         
     | 
| 
       64 
     | 
    
         
            -
                      !CommonPath.included_in?(path, Delfos.application_directories)
         
     | 
| 
       65 
     | 
    
         
            -
                    end
         
     | 
| 
       66 
     | 
    
         
            -
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
                def cache
         
     | 
| 
      
 49 
     | 
    
         
            +
                  @cache ||= {}
         
     | 
| 
       67 
50 
     | 
    
         
             
                end
         
     | 
| 
       68 
51 
     | 
    
         
             
              end
         
     | 
| 
       69 
52 
     | 
    
         
             
            end
         
     |