Created
April 28, 2012 16:56
-
-
Save sck/2520212 to your computer and use it in GitHub Desktop.
Reads DTrace output to fix Adobe's filenames on OS X with case-sensitive volumes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #! /usr/bin/env ruby | |
| # About | |
| # | |
| # This program tries to fix Adobe's issues with case-sensitive volumes by | |
| # using DTrace to log which files cannot be opened and then trying to | |
| # generate a shell script which will rename the files to the names as | |
| # Adobe wants them. | |
| # | |
| # USAGE: | |
| # 1. Open a shell and execute the following dtrace command (change | |
| # missing.files.for.photoshop at the end to illustrator, etc.): | |
| # % sudo dtrace -n 'syscall::*stat*:entry,syscall::*open*:entry /strstr(execname, "Adobe")!=0/ { self->filename = arg0; } syscall::*stat*:return,syscall::*open*:return /strstr(execname, "Adobe")!=0 && errno != 0/ { printf("<%s> %d", copyinstr(self->filename), errno); }' >> missing.files.for.photoshop | |
| # 2. Open the Adobe program you are trying to fix | |
| # 3. (Keep dtrace running) | |
| # 4. Run this script | |
| # % ruby fixAdobeCaseInsensitivePaths.rb < missing.files.for.photoshop | |
| # It should print out something like: | |
| # | correct_name="[...]" | |
| # | existing_name="[...]" | |
| # | if test -d "$existing_name"; then | |
| # | |
| # Save the output: | |
| # % ruby fixAdobeCaseInsensitivePaths.rb < missing.files.for.photoshop | |
| # > fixAdobePhotoshop1.sh | |
| # | |
| # 5. Run the generated shell script as root (You may want to look at the | |
| # script before running it as root) | |
| # % sudo sh fixAdobePhotoshop1.sh | |
| # 6. Repeat from step 2, now call the script fixAdobePhotoshopN.sh. | |
| # Repeat until Adobe program runs again without errors | |
| # | |
| $adobe_cache={} | |
| $have_moved={} | |
| $all_adobe_files=[] | |
| $true_name_in_current_fs = {} | |
| #$all_locales=`locale -a`.split(/\n/).map {|l| l.gsub(/\..*/, "") }.sort.uniq | |
| class String | |
| def split_path; split(File::SEPARATOR); end | |
| def fixify | |
| es = split_path | |
| es.each_with_index{|e,i| | |
| np = $have_moved[File.join(es[0..i])] | |
| if np | |
| es[i] = np.split_path[-1] | |
| end | |
| } | |
| File.join(es) | |
| end | |
| end | |
| def fill_adobe_cache(dir) | |
| return if $adobe_cache[dir] | |
| files = Dir["#{dir}/**/*"] | |
| files.each {|f| | |
| $all_adobe_files.push(f) | |
| $true_name_in_current_fs[f.downcase] = f | |
| } | |
| $adobe_cache[dir] = files.inject({}) {|h,v| h[v.downcase] = v; h} | |
| end | |
| def fix_paths(existing, correct) | |
| ee = existing.split_path | |
| ce = correct.split_path | |
| raise "different sizes!" if ce.size != ee.size | |
| c = 0 | |
| fixed = false | |
| begin | |
| if ee[c] != ce[c] | |
| correct_name = File.join(ce[0..c]) | |
| existing_name = File.join(ee[0..c]) | |
| ee[c] = ce[c] | |
| if !$have_moved.has_key?(existing_name) | |
| fixed = true | |
| $have_moved[existing_name] = correct_name | |
| puts <<EOFIX1 | |
| correct_name=#{correct_name.inspect} | |
| existing_name=#{existing_name.inspect} | |
| EOFIX1 | |
| true_existing_name = $true_name_in_current_fs[existing_name.downcase] | |
| if File.exists?(true_existing_name) | |
| if File.directory?(true_existing_name) | |
| puts <<EOFIX2 | |
| if test -d "$existing_name"; then | |
| echo "DIR: $correct_name" | |
| mv "$existing_name" "$correct_name" | |
| elif test \! -d "$correct_name"; then | |
| echo "Missing correct DIR: $correct_name" | |
| fi | |
| EOFIX2 | |
| else | |
| puts <<EOFIX3 | |
| if test -f "$existing_name"; then | |
| echo "FILE: $correct_name" | |
| mv "$existing_name" "$correct_name" | |
| elif test \! -f "$correct_name"; then | |
| echo "Missing correct FILE: $correct_name" | |
| fi | |
| EOFIX3 | |
| end | |
| end | |
| end | |
| end | |
| c += 1 | |
| end while c <= ce.size | |
| fixed | |
| end | |
| def generic_fix(_existing_name) | |
| existing_name = _existing_name.fixify | |
| ee = existing_name.split_path | |
| fix_paths(existing_name, File.join(ee[0..-2], "A")) if | |
| ee[-2] == "Versions" && ee[-1] == "a" | |
| fix_paths(existing_name, File.join(ee[0..-2], "Resources")) if | |
| ee[-1] == "resources" | |
| #if ee[-2].downcase == "resources" && ee[-1] =~ /^([a-z]+)_([a-z]+)\.lproj$/ | |
| # locale1 = $1 | |
| # locale2 = $2 | |
| # fix_paths(existing_name, | |
| # File.join(ee[0..-2], "#{locale1}_#{locale2.upcase}.lproj")) | |
| #end | |
| if ee[-2].downcase == "lmresources" && ee[-1] =~ /^([a-z]+)_([a-z]+)/ | |
| locale1 = $1 | |
| locale2 = $2 | |
| fix_paths(existing_name, | |
| File.join(ee[0..-2], "#{locale1}_#{locale2.upcase}")) | |
| end | |
| if ee[-3].downcase == "lmresources" && ee[-1] == "Main.zdct" | |
| fix_paths(existing_name, File.join(ee[0..-2], "main.zdct")) | |
| end | |
| end | |
| #f = File.open(STDIN, "r") | |
| while line = STDIN.gets | |
| line.chomp! | |
| m = /<([^>]*)>/.match(line) | |
| next if !m | |
| correct_name = File.expand_path(m[1]) | |
| next if File.exists?(correct_name) | |
| if /(^.*?Adobe [^\/]*)/.match(correct_name) | |
| adobe_dir = $1 | |
| correct_name_dc = correct_name.downcase | |
| fill_adobe_cache(adobe_dir) | |
| existing_name = $adobe_cache[adobe_dir][correct_name_dc] | |
| fix_paths(existing_name, correct_name) if existing_name | |
| end | |
| end | |
| $all_adobe_files.each{|f| generic_fix(f) } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment