delfos 0.0.1.pre.beta

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 504300a4ec558fbb0620996b4f1452dfd7f7424c
4
+ data.tar.gz: cf3adbd6030184d208a52d7586a816cc1d365668
5
+ SHA512:
6
+ metadata.gz: be9e77733e7d6af4ac90e62a5bbfac8ae056dbd2b6839e4a16e0c82960e64dd83d93ef8b72787b1b411f992687a67327790a3e9a9367c0dfeabe503c66d931a4
7
+ data.tar.gz: 6358c9cf62d2a2db3cf12b1fd025edc65e71c3982ad3d1d56a1d8adfb871777111da61f1dcb62ad17a213069666ce59594c24a4a75fc951991610998bf2d8b9b
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+ require "delfos/version"
3
+ require "delfos/method_logging"
4
+ require "delfos/neo4j/query_execution"
5
+ require "delfos/neo4j/informer"
6
+
7
+ module Delfos
8
+ class << self
9
+ def check_setup!
10
+ raise "Delfos.setup! has not been called" unless neo4j_config && logger
11
+ end
12
+
13
+ def wipe_db!
14
+ Delfos.setup!(application_directories: [])
15
+ Delfos::Neo4j::QueryExecution.execute <<-QUERY
16
+ MATCH (m)-[rel]->(n)
17
+ DELETE m,rel,n
18
+ QUERY
19
+ end
20
+
21
+ def reset!
22
+ @application_directories = []
23
+ @neo4j_config = nil
24
+ @logger = nil
25
+ remove_patching!
26
+ end
27
+
28
+ def remove_patching!
29
+ load "delfos/remove_patching.rb"
30
+ begin
31
+ Delfos::Patching.instance_eval { @added_methods = nil }
32
+ rescue
33
+ nil
34
+ end
35
+ end
36
+
37
+ def setup!(
38
+ connection_type: :server_db,
39
+ logger: Delfos::Neo4j::Informer.new,
40
+ host:"http://localhost:7474",
41
+ auth: { basic_auth: { username: "neo4j", password: "password" } },
42
+ application_directories: nil)
43
+
44
+ @application_directories = application_directories.map{|f| Pathname.new(File.expand_path(f.to_s))}
45
+ @logger = logger
46
+
47
+ @neo4j_config = [connection_type, host, auth]
48
+
49
+ perform_patching!
50
+ end
51
+
52
+ def perform_patching!
53
+ load "delfos/perform_patching.rb"
54
+ end
55
+
56
+ attr_reader :application_directories, :neo4j_config
57
+ end
58
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+ require "pathname"
3
+
4
+ module Delfos
5
+ module CommonPath
6
+ class << self
7
+ SEPARATOR = "/"
8
+
9
+ def included_in?(p1, paths)
10
+ paths = paths.map do |p2|
11
+ common = common_parent_directory_path(p1, p2)
12
+ common.to_s.length >= p2.to_s.length
13
+ end
14
+
15
+ paths.compact.detect { |v| v }
16
+ end
17
+
18
+ def common_parent_directory_path(path_a, path_b)
19
+ dirs = [File.expand_path(path_a.to_s), File.expand_path(path_b.to_s)]
20
+
21
+ dir1, dir2 = dirs.minmax.map { |dir| dir.split(SEPARATOR) }
22
+
23
+ path_from(dir1, dir2, path_a, path_b)
24
+ end
25
+
26
+ private
27
+
28
+ def path_from(dir1, dir2, path_a, path_b)
29
+ common_path = common_path(dir1, dir2)
30
+ common_path, path_a, path_b = append_trailing_slashes!(common_path, path_a, path_b)
31
+
32
+ if valid_length?(common_path, path_a, path_b)
33
+ Pathname.new(common_path)
34
+ end
35
+ end
36
+
37
+ def valid_length?(common_path, path_a, path_b)
38
+ (common_path.to_s.length <= path_a.to_s.length) || (common_path.to_s.length <= path_b.to_s.length)
39
+ end
40
+
41
+ def common_path(dir1, dir2)
42
+ dir1.
43
+ zip(dir2).
44
+ take_while { |dn1, dn2| dn1 == dn2 }.
45
+ map(&:first).
46
+ join(SEPARATOR)
47
+ end
48
+
49
+ def append_trailing_slashes!(*paths)
50
+ paths.map do |path|
51
+ if Pathname.new(path).directory?
52
+ path += SEPARATOR if path && path.to_s[-1] != SEPARATOR
53
+ end
54
+
55
+ path
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,133 @@
1
+ # frozen_string_literal: true
2
+ require_relative "relation"
3
+
4
+ module Delfos
5
+ module Distance
6
+ class Calculation
7
+ attr_reader :path_a, :path_b
8
+
9
+ def initialize(path_a, path_b)
10
+ @path_a = path_a
11
+ @path_b = path_b
12
+ end
13
+
14
+ attr_reader :traversal_a, :traversal_b
15
+
16
+ def traversals
17
+ result = []
18
+ path = traversal_path
19
+
20
+ path.each_cons(2) do |start, finish|
21
+ klass = klass_for(start, finish)
22
+ result.push(klass.new(start, finish))
23
+ end
24
+
25
+ result
26
+ end
27
+
28
+ def klass_for(a, b)
29
+ return ChildFile if b + ".." == a
30
+ Relation
31
+ end
32
+
33
+ def sum_traversals
34
+ traversals.inject(0) { |a, e| a + e.distance }
35
+ end
36
+
37
+ def sum_possible_traversals
38
+ traversals.inject(0) { |a, e| a + e.possible_length }
39
+ end
40
+
41
+ def sibling_directories(path)
42
+ siblings(path).select { |f| File.directory?(f) }
43
+ end
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
+ def traversal_path
57
+ TraversalPathCalculator.new(path_a, path_b).path
58
+ end
59
+
60
+ class TraversalPathCalculator
61
+ attr_reader :path_a, :path_b
62
+
63
+ def initialize(path_a, path_b)
64
+ @path_a = path_a
65
+ @path_b = path_b
66
+ end
67
+
68
+ def path
69
+ return [path_a, path_b] if same_directory?
70
+
71
+ current_path = path_a
72
+
73
+ traversal.descend do |p|
74
+ current_path = full(path_a, p)
75
+ result.process(current_path)
76
+ end
77
+
78
+ result
79
+ end
80
+
81
+ def same_directory?
82
+ path_a.dirname == path_b.dirname
83
+ end
84
+
85
+ def result
86
+ @result ||= Result.new([path_a])
87
+ end
88
+
89
+ def traversal
90
+ path_b.relative_path_from(path_a)
91
+ end
92
+
93
+ def full(start, traversal)
94
+ start.realpath + Pathname.new(traversal)
95
+ end
96
+
97
+ class Result < Array
98
+ def initialize(*args)
99
+ super
100
+ @in_parent = false
101
+ end
102
+
103
+ def process(i)
104
+ if @in_parent
105
+ @in_parent = false
106
+ remove_parent(i)
107
+ else
108
+ add_item(i)
109
+ end
110
+ end
111
+
112
+ private
113
+
114
+ def add_item(i)
115
+ @in_parent = ((last && last + "..") == i)
116
+ push i
117
+ end
118
+
119
+ def remove_parent(i)
120
+ return unless same_dir?(i)
121
+
122
+ pop
123
+ push(i)
124
+ end
125
+
126
+ def same_dir?(i)
127
+ self[-2] && self[-2].dirname == i.dirname
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+ module Delfos
3
+ module Distance
4
+ class Relation
5
+ attr_reader :start_path, :finish_path
6
+
7
+ def initialize(start_path, finish_path)
8
+ @start_path = start_path
9
+ @finish_path = finish_path
10
+ end
11
+
12
+ def other_files
13
+ RelatedPaths.new(start_path).files
14
+ end
15
+
16
+ def other_directories
17
+ RelatedPaths.new(start_path).directories
18
+ end
19
+
20
+ def distance
21
+ return traversed_files.length if both_files?
22
+ return traversed_directories.length if both_directories?
23
+
24
+ traversed_files.length + traversed_directories.length
25
+ end
26
+
27
+ def possible_length
28
+ other_files.length + other_directories.length
29
+ end
30
+
31
+ def traversed_files
32
+ start_at_end = (start_path.file? && finish_path.directory?)
33
+
34
+ subset_to_traverse(collection: other_files,
35
+ start: start_path,
36
+ finish: finish_path,
37
+ start_at_end: start_at_end)
38
+ end
39
+
40
+ def traversed_directories
41
+ start_at_end = (start_path.file? && finish_path.directory?) || (start_path.directory? && finish_path.file?)
42
+
43
+ subset_to_traverse(collection: other_directories,
44
+ start: start_path,
45
+ finish: finish_path,
46
+ start_at_end: start_at_end)
47
+ end
48
+
49
+ def subset_to_traverse(collection:, start:, finish:, start_at_end: true)
50
+ start_index, finish_index = indexes_from(collection, start, finish, start_at_end)
51
+
52
+ Array collection[start_index..finish_index]
53
+ end
54
+
55
+ private
56
+
57
+ def both_files?
58
+ start_path.file? && finish_path.file?
59
+ end
60
+
61
+ def both_directories?
62
+ start_path.directory? && finish_path.directory?
63
+ end
64
+
65
+ def indexes_from(collection, start, finish, start_at_end)
66
+ start_index = index_from(collection, start, start_at_end: start_at_end)
67
+ finish_index = index_from(collection, finish, start_at_end: start_at_end, reverse: true)
68
+
69
+ if start_index.zero? && finish_index.zero?
70
+ finish_index = collection.length - 1
71
+ end
72
+
73
+ [start_index, finish_index].sort
74
+ end
75
+
76
+ def index_from(collection, value, reverse: false, start_at_end: false)
77
+ index = collection.index value
78
+
79
+ if index.nil?
80
+ index = start_at_end && !reverse ? collection.length - 1 : 0
81
+ end
82
+
83
+ index
84
+ end
85
+
86
+ class RelatedPaths
87
+ attr_reader :path
88
+
89
+ def initialize(path)
90
+ @path = path
91
+ end
92
+
93
+ def files
94
+ all.select(&:file?)
95
+ end
96
+
97
+ def directories
98
+ all.select(&:directory?)
99
+ end
100
+
101
+ private
102
+
103
+ def all
104
+ Dir.glob(path.dirname + "*").map { |f| Pathname.new(f) }
105
+ end
106
+ end
107
+ end
108
+
109
+ class ChildFile < Relation
110
+ def other_files
111
+ RelatedPaths.new(start_path + "*").files
112
+ end
113
+
114
+ def other_directories
115
+ RelatedPaths.new(start_path + "*").directories
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,74 @@
1
+ require_relative "neo4j/execution_persistence"
2
+
3
+ module Delfos
4
+ class ExecutionChain
5
+ METHOD_CHAIN_MUTEX = Mutex.new
6
+
7
+ def self.reset!
8
+ METHOD_CHAIN_MUTEX.synchronize do
9
+ Thread.current[:_delfos__execution_chain__method_chain] = nil
10
+ end
11
+ end
12
+
13
+ def self.method_chain
14
+ METHOD_CHAIN_MUTEX.synchronize do
15
+ Thread.current[:_delfos__execution_chain__method_chain] ||= new
16
+ end
17
+ end
18
+
19
+ def self.push(method_object)
20
+ method_chain.push(method_object)
21
+ end
22
+
23
+ def self.pop
24
+ method_chain.pop
25
+ end
26
+
27
+ def push(method_object)
28
+ self.call_sites.push(method_object)
29
+ self.stack_depth += 1
30
+
31
+ self.execution_count += self.stack_depth == 1 ? 1 : 0
32
+ end
33
+
34
+ def pop
35
+ popping_empty_stack! if self.stack_depth == 0
36
+
37
+ self.stack_depth -= 1
38
+
39
+ save_and_reset! if self.stack_depth == 0
40
+ end
41
+
42
+ def stack_depth
43
+ @stack_depth ||= 0
44
+ end
45
+
46
+ def execution_count
47
+ @execution_count ||= 0
48
+ end
49
+
50
+ def call_sites
51
+ @call_sites ||= []
52
+ end
53
+
54
+ def step_count
55
+ call_sites.length
56
+ end
57
+
58
+ private
59
+
60
+ class PoppingEmptyStackError < StandardError
61
+ end
62
+
63
+ def popping_empty_stack!
64
+ raise PoppingEmptyStackError
65
+ end
66
+
67
+ def save_and_reset!
68
+ Neo4j::ExecutionPersistence.save!(self) if call_sites.length > 0
69
+ self.call_sites = []
70
+ end
71
+
72
+ attr_writer :stack_depth, :step_count, :execution_count, :call_sites
73
+ end
74
+ end