Skip to content

Instantly share code, notes, and snippets.

@acdha
Created August 15, 2009 20:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save acdha/168447 to your computer and use it in GitHub Desktop.
Save acdha/168447 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
"""
Force Aperture to reindex data after it corrupts its thumbnails, previews, or image paths
"""
from Cocoa import NSDictionary
import stat
import os
import sys
from xml.parsers.expat import ExpatError
import shutil
def process_ap_originals(arg, dirname, files):
for name in files:
filename = os.path.join(dirname, name)
try:
if name.endswith('.apfile'):
process_apfile(filename)
elif name.endswith('.apversion'):
process_apversion(filename)
elif name.startswith("AP."):
os.unlink(filename)
elif name in ["Previews", "Thumbnails"]:
shutil.rmtree(filename)
except ExpatError, e:
print >>sys.stderr, "ERROR: Malformed .plist %s" % filename
except (ValueError, RuntimeError), e:
print >>sys.stderr, "ERROR: file %s: %s" % (filename, e)
def process_apfile(apfile):
pl = NSDictionary.dictionaryWithContentsOfFile_(apfile)
if not pl:
raise RuntimeError("Invalid plist file: %s" % apfile)
if not 'imagePath' in pl:
print "No imagePath in apfile %s" % apfile
return
if pl['imagePath'].startswith("Pictures"):
# NOTE: We have to strip the leading / for compatibility:
pl['imagePath'] = os.path.realpath(os.path.join(os.path.expanduser("~", pl['imagePath']))).lstrip("/")
img_path = '/' + pl['imagePath']
if not os.path.exists(img_path):
possible_path = apfile.replace('.apfile', '')
if os.path.exists(possible_path):
possible_path = os.path.realpath(possible_path)[1:]
assert(os.path.exists("/" + possible_path))
print "%s: Updating imagePath from %s to %s" % (apfile, img_path, possible_path)
pl['imagePath'] = possible_path
img_path = "/" + possible_path
else:
print >>sys.stderr, "%s references missing %s!" % (apfile, img_path)
return
img_size = int(os.stat(img_path)[stat.ST_SIZE])
if pl['fileSize'] != img_size:
print "%s stored file size was %d but the file is actually %d" % (img_path, pl['fileSize'], img_size)
pl['fileSize'] = img_size
os.rename(apfile, apfile + ".delme")
pl.writeToFile_atomically_(apfile, True)
def process_apversion(apversion):
pl = NSDictionary.dictionaryWithContentsOfFile_(apversion)
if not pl:
raise RuntimeError("Invalid plist file: %s" % apversion)
for k in ['masterThumbnailCacheIndex', 'thumbnailCacheIndex', 'tinyCacheIndex', 'miniCacheIndex', 'thumbnailPreviewPath']:
if k in pl:
del(pl[k])
pl['thumbnailsCurrent'] = 0
pl['thumbnailRendered'] = 0
os.rename(apversion, apversion + ".delme")
pl.writeToFile_atomically_(apversion, True)
os.path.walk('Pictures/', process_ap_originals, None)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment