Class: Dotsync::Mapping
- Inherits:
-
Object
show all
- Includes:
- PathUtils
- Defined in:
- lib/dotsync/models/mapping.rb
Overview
Mapping represents a source-to-destination path pair for synchronization.
A mapping defines what should be synced (src -> dest), with optional filters:
only: whitelist of paths to include (everything else is excluded)
ignore: blacklist of paths to exclude
force: enable removal detection (find dest files not in src)
Path Matching Methods
The class provides several methods for path filtering, each with specific use cases:
- #include?(path): Returns true if path is inside an inclusion. Used for file filtering.
- #bidirectional_include?(path): Returns true if path is inside OR contains an inclusion.
Used during directory traversal to allow descending into parent directories.
- #should_prune_directory?(path): Returns true if a directory subtree can be skipped entirely.
This is a PERFORMANCE OPTIMIZATION for Find.prune - see DirectoryDiffer for details.
Constant Summary
Constants included
from PathUtils
PathUtils::ENV_VARS_COLOR
Instance Attribute Summary collapse
Instance Method Summary
collapse
Methods included from PathUtils
#colorize_env_vars, #expand_env_vars, #extract_env_vars, #path_is_parent_or_same?, #relative_to_absolute, #sanitize_path, #translate_tmp_path
Constructor Details
#initialize(attributes) ⇒ Mapping
Returns a new instance of Mapping.
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
# File 'lib/dotsync/models/mapping.rb', line 26
def initialize(attributes)
@original_src = attributes["src"]
@original_dest = attributes["dest"]
@original_ignores = Array(attributes["ignore"])
@original_only = Array(attributes["only"])
@force = attributes["force"] || false
@hooks = Array(attributes["hooks"])
@sync_type = attributes["sync_type"]
@sanitized_src, @sanitized_dest, @sanitized_ignores, @sanitized_only = process_paths(
@original_src,
@original_dest,
@original_ignores,
@original_only
)
end
|
Instance Attribute Details
#hooks ⇒ Object
Returns the value of attribute hooks.
63
64
65
|
# File 'lib/dotsync/models/mapping.rb', line 63
def hooks
@hooks
end
|
#original_dest ⇒ Object
Returns the value of attribute original_dest.
24
25
26
|
# File 'lib/dotsync/models/mapping.rb', line 24
def original_dest
@original_dest
end
|
#original_ignores ⇒ Object
Returns the value of attribute original_ignores.
24
25
26
|
# File 'lib/dotsync/models/mapping.rb', line 24
def original_ignores
@original_ignores
end
|
#original_only ⇒ Object
Returns the value of attribute original_only.
24
25
26
|
# File 'lib/dotsync/models/mapping.rb', line 24
def original_only
@original_only
end
|
#original_src ⇒ Object
Returns the value of attribute original_src.
24
25
26
|
# File 'lib/dotsync/models/mapping.rb', line 24
def original_src
@original_src
end
|
#sync_type ⇒ Object
Returns the value of attribute sync_type.
24
25
26
|
# File 'lib/dotsync/models/mapping.rb', line 24
def sync_type
@sync_type
end
|
Instance Method Details
#apply_to(path) ⇒ Object
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
|
# File 'lib/dotsync/models/mapping.rb', line 154
def apply_to(path)
relative_path = if Pathname.new(path).absolute?
path.delete_prefix(File.join(src, "/"))
else
path
end
Dotsync::Mapping.new(
"src" => File.join(@original_src, relative_path),
"dest" => File.join(@original_dest, relative_path),
"force" => @force,
"only" => @only,
"ignore" => @original_ignores
)
end
|
#backup_basename ⇒ Object
124
125
126
127
128
|
# File 'lib/dotsync/models/mapping.rb', line 124
def backup_basename
return unless valid?
return File.dirname(dest) unless File.exist?(dest)
File.basename(dest)
end
|
#backup_possible? ⇒ Boolean
120
121
122
|
# File 'lib/dotsync/models/mapping.rb', line 120
def backup_possible?
valid? && File.exist?(dest)
end
|
#bidirectional_include?(path) ⇒ Boolean
176
177
178
179
180
|
# File 'lib/dotsync/models/mapping.rb', line 176
def bidirectional_include?(path)
return true unless has_inclusions?
return true if path == src
inclusions.any? { |inclusion| inclusion_matches?(inclusion, path) || inclusion_is_ancestor?(path, inclusion) }
end
|
#decorated_dest ⇒ Object
150
151
152
|
# File 'lib/dotsync/models/mapping.rb', line 150
def decorated_dest
colorize_env_vars(original_dest)
end
|
#decorated_src ⇒ Object
146
147
148
|
# File 'lib/dotsync/models/mapping.rb', line 146
def decorated_src
colorize_env_vars(original_src)
end
|
#dest ⇒ Object
47
48
49
|
# File 'lib/dotsync/models/mapping.rb', line 47
def dest
@sanitized_dest
end
|
#directories? ⇒ Boolean
90
91
92
|
# File 'lib/dotsync/models/mapping.rb', line 90
def directories?
File.directory?(src) && File.directory?(dest)
end
|
#file_changed? ⇒ Boolean
112
113
114
115
116
117
118
|
# File 'lib/dotsync/models/mapping.rb', line 112
def file_changed?
return false unless files_present?
return true if File.size(src) != File.size(dest)
FileUtils.compare_file(src, dest) == false
end
|
#file_present_in_src_only? ⇒ Boolean
102
103
104
|
# File 'lib/dotsync/models/mapping.rb', line 102
def file_present_in_src_only?
File.file?(src) && !File.exist?(dest) && File.directory?(File.dirname(dest))
end
|
#files? ⇒ Boolean
94
95
96
|
# File 'lib/dotsync/models/mapping.rb', line 94
def files?
files_present? || file_present_in_src_only?
end
|
#files_present? ⇒ Boolean
98
99
100
|
# File 'lib/dotsync/models/mapping.rb', line 98
def files_present?
File.file?(src) && File.file?(dest)
end
|
#force? ⇒ Boolean
59
60
61
|
# File 'lib/dotsync/models/mapping.rb', line 59
def force?
@force
end
|
#has_hooks? ⇒ Boolean
65
66
67
|
# File 'lib/dotsync/models/mapping.rb', line 65
def has_hooks?
@hooks.any?
end
|
#has_inclusions? ⇒ Boolean
69
70
71
|
# File 'lib/dotsync/models/mapping.rb', line 69
def has_inclusions?
@original_only.any?
end
|
#icons ⇒ Object
130
131
132
133
134
135
136
137
138
|
# File 'lib/dotsync/models/mapping.rb', line 130
def icons
msg = []
msg << Icons.force if force?
msg << Icons.only if has_inclusions?
msg << Icons.ignore if has_ignores?
msg << Icons.hook if has_hooks?
msg << Icons.invalid unless valid?
msg.join
end
|
#ignore?(path) ⇒ Boolean
182
183
184
|
# File 'lib/dotsync/models/mapping.rb', line 182
def ignore?(path)
ignores.any? { |ignore| path.start_with?(ignore) }
end
|
#ignores ⇒ Object
51
52
53
|
# File 'lib/dotsync/models/mapping.rb', line 51
def ignores
@sanitized_ignores
end
|
#include?(path) ⇒ Boolean
170
171
172
173
174
|
# File 'lib/dotsync/models/mapping.rb', line 170
def include?(path)
return true unless has_inclusions?
return true if path == src
inclusions.any? { |inclusion| inclusion_matches?(inclusion, path) }
end
|
#inclusions ⇒ Object
55
56
57
|
# File 'lib/dotsync/models/mapping.rb', line 55
def inclusions
@sanitized_only
end
|
#manifest_key ⇒ Object
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
# File 'lib/dotsync/models/mapping.rb', line 73
def manifest_key
return nil unless @sync_type
shorthand_base = SyncMappings::SHORTHANDS.dig(@sync_type, :local)
return @sync_type unless shorthand_base
expanded_base = sanitize_path(shorthand_base)
if dest == expanded_base
@sync_type
elsif dest.start_with?("#{expanded_base}/")
subpath = dest.delete_prefix("#{expanded_base}/")
"#{@sync_type}--#{subpath}"
else
@sync_type
end
end
|
#should_prune_directory?(path) ⇒ Boolean
Determines if a directory subtree can be entirely skipped during traversal.
PERFORMANCE OPTIMIZATION: This method enables Find.prune in DirectoryDiffer.
When walking large destination directories (e.g., ~/.config with 8,686 files),
pruning irrelevant subtrees avoids visiting thousands of files that will never
match the only filter. This reduced scan time from 7.2s to 0.5s in benchmarks.
A directory should be pruned if:
- It's ignored (in the ignore list), OR
- It has inclusions AND the path is neither:
- Inside an inclusion (would be synced)
- A parent of an inclusion (might contain synced files)
205
206
207
208
209
|
# File 'lib/dotsync/models/mapping.rb', line 205
def should_prune_directory?(path)
return true if ignore?(path)
return false unless has_inclusions?
!bidirectional_include?(path)
end
|
#skip?(path) ⇒ Boolean
186
187
188
|
# File 'lib/dotsync/models/mapping.rb', line 186
def skip?(path)
ignore?(path) || !include?(path)
end
|
#src ⇒ Object
43
44
45
|
# File 'lib/dotsync/models/mapping.rb', line 43
def src
@sanitized_src
end
|
#to_s ⇒ Object
140
141
142
143
144
|
# File 'lib/dotsync/models/mapping.rb', line 140
def to_s
msg = "#{decorated_src} → #{decorated_dest}"
msg += " #{icons}" if icons != ""
msg
end
|
#valid? ⇒ Boolean
106
107
108
109
110
|
# File 'lib/dotsync/models/mapping.rb', line 106
def valid?
return false unless paths_are_distinct?
return false unless paths_not_nested?
directories? || files? || file_present_in_src_only?
end
|