dotsync 0.1.26 → 0.1.27
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/Gemfile.lock +1 -1
- data/exe/dotsync +5 -0
- data/lib/dotsync/actions/concerns/mappings_transfer.rb +18 -1
- data/lib/dotsync/actions/concerns/output_sections.rb +2 -1
- data/lib/dotsync/actions/pull_action.rb +1 -1
- data/lib/dotsync/actions/push_action.rb +1 -1
- data/lib/dotsync/loaders/pull_loader.rb +1 -0
- data/lib/dotsync/loaders/push_loader.rb +1 -0
- data/lib/dotsync/models/diff.rb +3 -2
- data/lib/dotsync/utils/content_diff.rb +82 -0
- data/lib/dotsync/utils/directory_differ.rb +18 -8
- data/lib/dotsync/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6d2cef06dff635c8202f87424d1532d0db5cfdf7e26e1c0c98daee44acdd12e4
|
|
4
|
+
data.tar.gz: 38484cab4e99854a8b54259e222ace225834000c9d9a6df8005dff8b1baa228c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 22d5fe759b17a723377363c22f05f77cedf57fd6ac41b4c8d379c2f2b2bf4fb42022a0c92707083356a096385fe51b1175c9865fb1f78fde58ba41b94be9fa17
|
|
7
|
+
data.tar.gz: 3fb40ad4ac4835cf0c3a45e8bb3d872197dc60bb79d04b8a6ff09d5626d6b92f63865b035d5eb7cc923f12319b4651e08ffe36e808296d002f88712e5bc54730
|
data/Gemfile.lock
CHANGED
data/exe/dotsync
CHANGED
|
@@ -51,6 +51,7 @@ opt_parser = OptionParser.new do |opts|
|
|
|
51
51
|
--only-config Show only the config section
|
|
52
52
|
--only-mappings Show only the mappings section
|
|
53
53
|
-v, --verbose Force showing all available information
|
|
54
|
+
--diff-content Show git-like content diff for modified files
|
|
54
55
|
--trace Show full error backtraces (for debugging)
|
|
55
56
|
--version Show version number
|
|
56
57
|
-h, --help Show this help message
|
|
@@ -112,6 +113,10 @@ opt_parser = OptionParser.new do |opts|
|
|
|
112
113
|
options[:verbose] = true
|
|
113
114
|
end
|
|
114
115
|
|
|
116
|
+
opts.on("--diff-content", "Show git-like content diff for modified files") do
|
|
117
|
+
options[:diff_content] = true
|
|
118
|
+
end
|
|
119
|
+
|
|
115
120
|
opts.on("--trace", "Show full error backtraces (for debugging)") do
|
|
116
121
|
options[:trace] = true
|
|
117
122
|
end
|
|
@@ -62,7 +62,7 @@ module Dotsync
|
|
|
62
62
|
logger.log("")
|
|
63
63
|
end
|
|
64
64
|
|
|
65
|
-
def show_differences
|
|
65
|
+
def show_differences(diff_content: false)
|
|
66
66
|
info("Differences:", icon: :diff)
|
|
67
67
|
differs.flat_map(&:additions).sort.each do |path|
|
|
68
68
|
logger.log("#{Icons.diff_created}#{path}", color: Colors.diff_additions)
|
|
@@ -75,6 +75,15 @@ module Dotsync
|
|
|
75
75
|
end
|
|
76
76
|
logger.log(" No differences") unless has_differences?
|
|
77
77
|
logger.log("")
|
|
78
|
+
|
|
79
|
+
show_content_diffs if diff_content && has_modifications?
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def show_content_diffs
|
|
83
|
+
info("Content Differences:", icon: :diff)
|
|
84
|
+
modification_pairs.each do |pair|
|
|
85
|
+
Dotsync::ContentDiff.new(pair[:src], pair[:dest], logger).display
|
|
86
|
+
end
|
|
78
87
|
end
|
|
79
88
|
|
|
80
89
|
def transfer_mappings
|
|
@@ -108,6 +117,14 @@ module Dotsync
|
|
|
108
117
|
differs.any? { |differ| differ.any? }
|
|
109
118
|
end
|
|
110
119
|
|
|
120
|
+
def has_modifications?
|
|
121
|
+
differs.any? { |differ| differ.modifications.any? }
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def modification_pairs
|
|
125
|
+
differs.flat_map(&:modification_pairs)
|
|
126
|
+
end
|
|
127
|
+
|
|
111
128
|
def confirm_action
|
|
112
129
|
total_changes = differs.sum { |diff| diff.additions.size + diff.modifications.size + diff.removals.size }
|
|
113
130
|
logger.log("")
|
|
@@ -12,7 +12,8 @@ module Dotsync
|
|
|
12
12
|
mappings_legend: !(quiet || options[:no_legend] || options[:no_mappings] || options[:only_diff]),
|
|
13
13
|
mappings: !(quiet || options[:no_mappings] || options[:only_diff]),
|
|
14
14
|
differences_legend: !(quiet || options[:no_legend] || options[:no_diff_legend] || options[:no_diff] || options[:only_config] || options[:only_mappings]),
|
|
15
|
-
differences: !(quiet || options[:no_diff] || options[:only_mappings] || options[:only_config])
|
|
15
|
+
differences: !(quiet || options[:no_diff] || options[:only_mappings] || options[:only_config]),
|
|
16
|
+
diff_content: options[:diff_content] || false
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
if verbose
|
|
@@ -15,7 +15,7 @@ module Dotsync
|
|
|
15
15
|
show_mappings_legend if output_sections[:mappings_legend]
|
|
16
16
|
show_mappings if output_sections[:mappings]
|
|
17
17
|
show_differences_legend if has_differences? && output_sections[:differences_legend]
|
|
18
|
-
show_differences if output_sections[:differences]
|
|
18
|
+
show_differences(diff_content: output_sections[:diff_content]) if output_sections[:differences]
|
|
19
19
|
|
|
20
20
|
return unless options[:apply]
|
|
21
21
|
|
|
@@ -13,7 +13,7 @@ module Dotsync
|
|
|
13
13
|
show_mappings_legend if output_sections[:mappings_legend]
|
|
14
14
|
show_mappings if output_sections[:mappings]
|
|
15
15
|
show_differences_legend if has_differences? && output_sections[:differences_legend]
|
|
16
|
-
show_differences if output_sections[:differences]
|
|
16
|
+
show_differences(diff_content: output_sections[:diff_content]) if output_sections[:differences]
|
|
17
17
|
|
|
18
18
|
return unless options[:apply]
|
|
19
19
|
|
data/lib/dotsync/models/diff.rb
CHANGED
|
@@ -3,12 +3,13 @@
|
|
|
3
3
|
module Dotsync
|
|
4
4
|
# Represents the differences between two directories
|
|
5
5
|
class Diff
|
|
6
|
-
attr_reader :additions, :modifications, :removals
|
|
6
|
+
attr_reader :additions, :modifications, :removals, :modification_pairs
|
|
7
7
|
|
|
8
|
-
def initialize(additions: [], modifications: [], removals: [])
|
|
8
|
+
def initialize(additions: [], modifications: [], removals: [], modification_pairs: [])
|
|
9
9
|
@additions = additions
|
|
10
10
|
@modifications = modifications
|
|
11
11
|
@removals = removals
|
|
12
|
+
@modification_pairs = modification_pairs
|
|
12
13
|
end
|
|
13
14
|
|
|
14
15
|
def any?
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Dotsync
|
|
4
|
+
class ContentDiff
|
|
5
|
+
COLORS = {
|
|
6
|
+
header: 103, # Purple for file headers
|
|
7
|
+
hunk: 36, # Cyan for @@ lines
|
|
8
|
+
addition: 34, # Blue for added lines (consistent with diff_additions)
|
|
9
|
+
deletion: 88, # Red for removed lines (consistent with diff_removals)
|
|
10
|
+
context: 240 # Gray for context lines
|
|
11
|
+
}.freeze
|
|
12
|
+
|
|
13
|
+
def initialize(src_path, dest_path, logger)
|
|
14
|
+
@src_path = src_path
|
|
15
|
+
@dest_path = dest_path
|
|
16
|
+
@logger = logger
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def display
|
|
20
|
+
return unless displayable?
|
|
21
|
+
|
|
22
|
+
diff_output = generate_diff
|
|
23
|
+
return if diff_output.empty?
|
|
24
|
+
|
|
25
|
+
display_header
|
|
26
|
+
colorize_and_display(diff_output)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
def displayable?
|
|
31
|
+
text_file?(@src_path) && text_file?(@dest_path)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def text_file?(path)
|
|
35
|
+
return false unless File.file?(path)
|
|
36
|
+
|
|
37
|
+
# Check if file appears to be text by reading first few bytes
|
|
38
|
+
begin
|
|
39
|
+
sample = File.read(path, 8192) || ""
|
|
40
|
+
# Binary files typically contain null bytes
|
|
41
|
+
!sample.include?("\x00")
|
|
42
|
+
rescue StandardError
|
|
43
|
+
false
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def generate_diff
|
|
48
|
+
# Use system diff with unified format
|
|
49
|
+
# diff returns exit code 1 when files differ, so we can't use backticks directly
|
|
50
|
+
output = `diff -u "#{@dest_path}" "#{@src_path}" 2>/dev/null`
|
|
51
|
+
output.lines.drop(2).join # Drop the first two header lines, we'll add our own
|
|
52
|
+
rescue StandardError
|
|
53
|
+
""
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def display_header
|
|
57
|
+
@logger.log("--- #{@dest_path}", color: COLORS[:header])
|
|
58
|
+
@logger.log("+++ #{@src_path}", color: COLORS[:header])
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def colorize_and_display(diff_output)
|
|
62
|
+
diff_output.each_line do |line|
|
|
63
|
+
color = line_color(line)
|
|
64
|
+
@logger.log(line.chomp, color: color)
|
|
65
|
+
end
|
|
66
|
+
@logger.log("")
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def line_color(line)
|
|
70
|
+
case line[0]
|
|
71
|
+
when "+"
|
|
72
|
+
COLORS[:addition]
|
|
73
|
+
when "-"
|
|
74
|
+
COLORS[:deletion]
|
|
75
|
+
when "@"
|
|
76
|
+
COLORS[:hunk]
|
|
77
|
+
else
|
|
78
|
+
COLORS[:context]
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -31,6 +31,7 @@ module Dotsync
|
|
|
31
31
|
def diff_mapping_directories
|
|
32
32
|
additions = []
|
|
33
33
|
modifications = []
|
|
34
|
+
modification_pairs = []
|
|
34
35
|
removals = []
|
|
35
36
|
|
|
36
37
|
Find.find(mapping_src) do |src_path|
|
|
@@ -48,6 +49,7 @@ module Dotsync
|
|
|
48
49
|
elsif File.file?(src_path) && File.file?(dest_path)
|
|
49
50
|
if files_differ?(src_path, dest_path)
|
|
50
51
|
modifications << rel_path
|
|
52
|
+
modification_pairs << { rel_path: rel_path, src: src_path, dest: dest_path }
|
|
51
53
|
end
|
|
52
54
|
end
|
|
53
55
|
end
|
|
@@ -67,21 +69,29 @@ module Dotsync
|
|
|
67
69
|
end
|
|
68
70
|
end
|
|
69
71
|
|
|
72
|
+
filtered_modifications = filter_ignores(modifications)
|
|
73
|
+
modification_pairs = modification_pairs.select { |pair| filtered_modifications.include?(pair[:rel_path]) }
|
|
74
|
+
|
|
70
75
|
additions = relative_to_absolute(filter_ignores(additions), mapping_original_dest)
|
|
71
|
-
modifications = relative_to_absolute(
|
|
76
|
+
modifications = relative_to_absolute(filtered_modifications, mapping_original_dest)
|
|
72
77
|
removals = relative_to_absolute(filter_ignores(removals), mapping_original_dest)
|
|
73
78
|
|
|
74
|
-
Dotsync::Diff.new(additions: additions, modifications: modifications, removals: removals)
|
|
79
|
+
Dotsync::Diff.new(additions: additions, modifications: modifications, removals: removals, modification_pairs: modification_pairs)
|
|
75
80
|
end
|
|
76
81
|
|
|
77
82
|
def diff_mapping_files
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
83
|
+
additions = []
|
|
84
|
+
modifications = []
|
|
85
|
+
modification_pairs = []
|
|
86
|
+
|
|
87
|
+
if @mapping.file_present_in_src_only?
|
|
88
|
+
additions << @mapping.original_dest
|
|
89
|
+
elsif @mapping.file_changed?
|
|
90
|
+
modifications << @mapping.original_dest
|
|
91
|
+
modification_pairs << { rel_path: File.basename(@mapping.original_dest), src: @mapping.src, dest: @mapping.dest }
|
|
84
92
|
end
|
|
93
|
+
|
|
94
|
+
Dotsync::Diff.new(additions: additions, modifications: modifications, modification_pairs: modification_pairs)
|
|
85
95
|
end
|
|
86
96
|
|
|
87
97
|
def filter_ignores(all_paths)
|
data/lib/dotsync/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dotsync
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.27
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- David Sáenz
|
|
@@ -334,6 +334,7 @@ files:
|
|
|
334
334
|
- lib/dotsync/runner.rb
|
|
335
335
|
- lib/dotsync/tasks/actions.rake
|
|
336
336
|
- lib/dotsync/utils/config_cache.rb
|
|
337
|
+
- lib/dotsync/utils/content_diff.rb
|
|
337
338
|
- lib/dotsync/utils/directory_differ.rb
|
|
338
339
|
- lib/dotsync/utils/file_transfer.rb
|
|
339
340
|
- lib/dotsync/utils/logger.rb
|