Properly handle special characters in file names.

This commit is contained in:
Markus Reiter 2017-10-11 15:32:39 +02:00
parent 56458f03fc
commit 04363b25a3
3 changed files with 26 additions and 18 deletions

View File

@ -94,6 +94,9 @@ Performance/Caller:
Style/Alias: Style/Alias:
EnforcedStyle: prefer_alias EnforcedStyle: prefer_alias
Style/AsciiComments:
Enabled: false
Style/AutoResourceCleanup: Style/AutoResourceCleanup:
Enabled: true Enabled: true

View File

@ -88,7 +88,7 @@ module Hbc
bomfile.close bomfile.close
Tempfile.open(["", ".list"]) do |filelist| Tempfile.open(["", ".list"]) do |filelist|
filelist.write(bom_filelist_from_path(mount)) filelist.puts(bom_filelist_from_path(mount))
filelist.close filelist.close
@command.run!("/usr/bin/mkbom", args: ["-s", "-i", filelist.path, "--", bomfile.path]) @command.run!("/usr/bin/mkbom", args: ["-s", "-i", filelist.path, "--", bomfile.path])
@ -98,16 +98,17 @@ module Hbc
end end
def bom_filelist_from_path(mount) def bom_filelist_from_path(mount)
Dir.chdir(mount) do # We need to use `find` here instead of Ruby in order to properly handle
Dir.glob("**/*", File::FNM_DOTMATCH).map do |path| # file names containing special characters, such as “e” + “´” vs. “é”.
next if skip_path?(Pathname(path)) @command.run("/usr/bin/find", args: [".", "-print0"], chdir: mount, print_stderr: false).stdout
(path == ".") ? path : path.prepend("./") .split("\0")
end.compact.join("\n").concat("\n") .reject { |path| skip_path?(mount, path) }
end .join("\n")
end end
def skip_path?(path) def skip_path?(mount, path)
dmg_metadata?(path) || system_dir_symlink?(path) path = Pathname(path.sub(%r{^\./}, ""))
dmg_metadata?(path) || system_dir_symlink?(mount, path)
end end
# unnecessary DMG metadata # unnecessary DMG metadata
@ -130,9 +131,10 @@ module Hbc
DMG_METADATA_FILES.include?(relative_root.basename.to_s) DMG_METADATA_FILES.include?(relative_root.basename.to_s)
end end
def system_dir_symlink?(path) def system_dir_symlink?(mount, path)
full_path = Pathname(mount).join(path)
# symlinks to system directories (commonly to /Applications) # symlinks to system directories (commonly to /Applications)
path.symlink? && MacOS.system_dir?(path.readlink) full_path.symlink? && MacOS.system_dir?(full_path.readlink)
end end
def mounts_from_plist(plist) def mounts_from_plist(plist)

View File

@ -10,12 +10,12 @@ module Hbc
class SystemCommand class SystemCommand
attr_reader :command attr_reader :command
def self.run(executable, options = {}) def self.run(executable, **options)
new(executable, options).run! new(executable, **options).run!
end end
def self.run!(command, options = {}) def self.run!(command, **options)
run(command, options.merge(must_succeed: true)) run(command, **options.merge(must_succeed: true))
end end
def run! def run!
@ -37,7 +37,7 @@ module Hbc
result result
end end
def initialize(executable, options) def initialize(executable, **options)
@executable = executable @executable = executable
@options = options @options = options
process_options! process_options!
@ -49,7 +49,7 @@ module Hbc
def process_options! def process_options!
options.extend(HashValidator) options.extend(HashValidator)
.assert_valid_keys :input, :print_stdout, :print_stderr, :args, :must_succeed, :sudo .assert_valid_keys :input, :print_stdout, :print_stderr, :args, :must_succeed, :sudo, :chdir
sudo_prefix = %w[/usr/bin/sudo -E --] sudo_prefix = %w[/usr/bin/sudo -E --]
sudo_prefix = sudo_prefix.insert(1, "-A") unless ENV["SUDO_ASKPASS"].nil? sudo_prefix = sudo_prefix.insert(1, "-A") unless ENV["SUDO_ASKPASS"].nil?
@command = [executable] @command = [executable]
@ -76,8 +76,11 @@ module Hbc
end end
def each_output_line(&b) def each_output_line(&b)
opts = {}
opts[:chdir] = options[:chdir] if options[:chdir]
raw_stdin, raw_stdout, raw_stderr, raw_wait_thr = raw_stdin, raw_stdout, raw_stderr, raw_wait_thr =
Open3.popen3(*expanded_command) Open3.popen3(*expanded_command, **opts)
write_input_to(raw_stdin) write_input_to(raw_stdin)
raw_stdin.close_write raw_stdin.close_write