moonshard 0.1.0 → 0.3.0

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.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/lib/moonshard.rb +68 -32
  3. data/moonshard.gemspec +1 -1
  4. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 93fffd8c4d7bb102f655c8062412d7ac5bfd816a5adfd87d2299551ee030db39
4
- data.tar.gz: 4e6e7961be6fc2b9379bdd3b054d3b9b013b0998c857eb1ac203d8ce471c351f
3
+ metadata.gz: d6f6a34f5d9df3e406dc7deb5abe08c9b3286d73f5a252096a22f717cb691539
4
+ data.tar.gz: 48376f7947cadd24a7066e23575c449fea4977662a3ba337f0c5ff05f1bda040
5
5
  SHA512:
6
- metadata.gz: 54cc25eb6933812d809e0b27948bf3eb9db825f37b947c4320aa0887dde5ac792aee8dacf6f8d6e0b45822581073258b041e14d22e8cf0a3a19d8b7bdef7623f
7
- data.tar.gz: 74c2cf709fc228d89684d97bdfb4ef69848859374f52e9900e9f57279a07f5dcead3aa07d58fa26cd9c1a84bb00ba397db50657ef8955b72dea3203e50d2db56
6
+ metadata.gz: a5047124bee729f517f154d913281e551bc4b15bbf7e024a35de3c83c748c38bcec2f2e2391c4a58cee1d3fb2bf7ad35c9bee3c2ee34fc4e18e9c9bd10285983
7
+ data.tar.gz: c5af09fde7932cd6d6f2e838741f1f8f07117fe56f5e0eb294eb8889ea04b080ddb544be59f4fc1bfe29ff23b4a9984198c567b0c11721ffd2b34e66fff2266f
data/lib/moonshard.rb CHANGED
@@ -2,6 +2,7 @@ require "json"
2
2
 
3
3
  module Moonshard
4
4
  DEFAULT_BACKUP_FILE = "original_files.json"
5
+ PLACEHOLDER = '##{'
5
6
 
6
7
  class Error < StandardError
7
8
  end
@@ -29,7 +30,7 @@ module Moonshard
29
30
 
30
31
  original_files.each do |file, content|
31
32
  begin
32
- File.write(file, content)
33
+ File.binwrite(file, content)
33
34
  puts "Restored: #{file}"
34
35
  rescue => e
35
36
  warn "Warning: cannot restore #{file}: #{e.message}"
@@ -50,55 +51,90 @@ module Moonshard
50
51
  Dir.glob(File.join(root_dir, "**", "*")).each do |file|
51
52
  next unless File.file?(file)
52
53
 
53
- # Don't process the backup JSON itself
54
+ # Don't process the backup JSON itself.
54
55
  next if File.expand_path(file) == backup_file
55
56
 
56
57
  begin
57
- content = File.read(file)
58
+ # Read as raw bytes so binary files don't cause UTF-8 errors.
59
+ content = File.binread(file)
58
60
  rescue => e
59
61
  warn "Warning: cannot read #{file}: #{e.message}"
60
62
  next
61
63
  end
62
64
 
63
- # Only process files containing ##{...}
64
- next unless content.match?(/##\{[^}]+\}/)
65
+ # Only consider files containing the ##{ marker.
66
+ next unless content.include?(PLACEHOLDER)
65
67
 
66
- # Save original content before replacement
67
- original_files[file] = content
68
+ begin
69
+ text = content.dup.force_encoding(Encoding::UTF_8)
68
70
 
69
- file_dir = File.dirname(file)
71
+ # Skip binary / invalid UTF-8 files.
72
+ unless text.valid_encoding?
73
+ warn "Skipping binary/non-UTF-8 file: #{file}"
74
+ next
75
+ end
70
76
 
71
- replaced = content.gsub(/^([ \t]*)##\{([^}]+)\}[ \t]*$/) do
72
- indentation = Regexp.last_match(1)
73
- referenced_file = Regexp.last_match(2)
77
+ file_dir = File.dirname(file)
74
78
 
75
- referenced_path = File.expand_path(
76
- referenced_file,
77
- file_dir
78
- )
79
+ replaced = text.gsub(/^([ \t]*)##\{([^}]+)\}[ \t]*$/) do
80
+ indentation = Regexp.last_match(1)
81
+ referenced_file = Regexp.last_match(2)
79
82
 
80
- unless File.file?(referenced_path)
81
- warn "Warning: file not found: #{referenced_path} (referenced from #{file})"
82
- next Regexp.last_match(0)
83
- end
83
+ referenced_path = File.expand_path(
84
+ referenced_file,
85
+ file_dir
86
+ )
84
87
 
85
- inserted_content = File.read(referenced_path).chomp
88
+ unless File.file?(referenced_path)
89
+ warn "Warning: file not found: #{referenced_path} " \
90
+ "(referenced from #{file})"
86
91
 
87
- # Apply the indentation of ##{...}
88
- # to every non-empty line.
89
- inserted_content.lines.map do |line|
90
- if line.strip.empty?
91
- line
92
- else
93
- indentation + line
92
+ next Regexp.last_match(0)
94
93
  end
95
- end.join
96
- end
97
94
 
98
- next if replaced == content
95
+ begin
96
+ inserted_content = File.binread(referenced_path)
97
+ inserted_content.force_encoding(Encoding::UTF_8)
98
+
99
+ unless inserted_content.valid_encoding?
100
+ warn "Warning: referenced file is not valid UTF-8: " \
101
+ "#{referenced_path}"
102
+
103
+ next Regexp.last_match(0)
104
+ end
105
+ rescue => e
106
+ warn "Warning: cannot read #{referenced_path}: #{e.message}"
107
+ next Regexp.last_match(0)
108
+ end
109
+
110
+ # Remove the final newline because the placeholder line
111
+ # already provides the newline.
112
+ inserted_content = inserted_content.chomp
113
+
114
+ # Apply the indentation from the ##{...} line to
115
+ # every non-empty line of the referenced file.
116
+ inserted_content.lines.map do |line|
117
+ if line.strip.empty?
118
+ line
119
+ else
120
+ indentation + line
121
+ end
122
+ end.join
123
+ end
124
+
125
+ next if replaced == text
126
+
127
+ # Save the original content before writing.
128
+ original_files[file] = text
99
129
 
100
- File.write(file, replaced)
101
- puts "Updated: #{file}"
130
+ File.binwrite(file, replaced)
131
+
132
+ puts "Updated: #{file}"
133
+ rescue ArgumentError => e
134
+ warn "Warning: cannot process #{file}: #{e.message}"
135
+ rescue => e
136
+ warn "Warning: cannot process #{file}: #{e.message}"
137
+ end
102
138
  end
103
139
 
104
140
  File.write(
data/moonshard.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = "moonshard"
3
- spec.version = "0.1.0"
3
+ spec.version = "0.3.0"
4
4
  spec.authors = ["Tommy Jeff"]
5
5
  spec.email = ["threcius@gmail.com"]
6
6
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: moonshard
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tommy Jeff