diff --git a/.gitignore b/.gitignore index 1dbd519..b5ec0ca 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,6 @@ +# Be careful about editing this file. It contains \r\r after "Icon". +*.pyc +/build +/dist +/folderify.egg-info Icon \ No newline at end of file diff --git a/README.md b/README.md index 743ad45..14c636f 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ git clone git://github.com/lgarron/folderify.git cd folderify - for file in examples/src/*.png; do ./folderify $file; done + for file in examples/src/*.png; do python -m folderify $file; done open examples/src/ You should see a bunch of new `.iconset` folders and `.icns` files that were automatically generated from the `.png` masks. @@ -22,7 +22,7 @@ Or try this: git clone git://github.com/lgarron/folderify.git cd folderify - ./folderify examples/src/folder_outline.png . + python -m folderify examples/src/folder_outline.png . The repository folder should now have an icon. diff --git a/folderify b/folderify deleted file mode 100755 index 047782e..0000000 --- a/folderify +++ /dev/null @@ -1,313 +0,0 @@ -#!/usr/bin/env python - -import argparse -import functools -import os.path -import platform -import shutil -import subprocess -import sys -import tempfile - -from string import Template - - -################################################################ - - -parser = argparse.ArgumentParser( - description="Generate a native OSX folder icon from a mask file.", - formatter_class=argparse.RawTextHelpFormatter -) - -exclusive = parser.add_mutually_exclusive_group() - -exclusive.add_argument( - "mask", - action="store", - nargs="?", - type=str, - help="Mask image file. For best results:\n\ -- Use a .png mask.\n\ -- Use a solid black design over a transparent background.\n\ -- Make sure the corner pixels of the mask image are transparent. They are used for empty margins.\n\ -- Make sure the icon is at least around 1024x1024, in order to look good at maximum Retina resolution.") - -parser.add_argument( - "target", - action="store", - nargs="?", - type=str, - help="Target file or folder. \ -If a target is specified, the resulting icon will be applied to the target file/folder. \ -Else, a .iconset folder and .icns file will be created in the same folder as mask \ -(you can use \"Get Info\" in Finder to copy the icon from the .icns file).") - -parser.add_argument( - "--reveal", "-r", - action="store_true", - help="Reveal the target (or resulting .icns file) in Finder.") - -local_osx_version = ".".join(platform.mac_ver()[0].split(".")[:2]) - -parser.add_argument( - "--osx_version", "-x", - type=str, - default=local_osx_version, - help=("Version of the OSX folder icon, e.g. \"10.9\" or \"10.10\". \ -Defaults to the version this computer is running (%s)." % local_osx_version)) - -parser.add_argument( - "--cache", "-c", - action="store_true", - help="Cache the mask icon in the cache dir.") - -parser.add_argument( - "--cache-dir", - type=str, - default=os.path.expanduser("~/.folderify/cache"), - help="Cache directory.") - -exclusive.add_argument( - "--restore-from-cache", - metavar="PATH", - type=str, - help="Restore folderified icon to the file/folder at PATH,\ -using the mask image in the cache for that path.") - -exclusive.add_argument( - "--restore-all-from-cache", - action="store_true", - help="Restore all paths that have been cached.") - - -################################################################ - - -args = parser.parse_args() - -if args.cache and not args.mask: - parser.error("Must specify mask in order to use --cache.") - - -################################################################ - - -data_folder = os.path.dirname(sys.argv[0]) - -if args.osx_version == "10.10": - folder_type = "Yosemite" -elif args.osx_version in ["10.5", "10.6", "10.7", "10.8", "10.9"]: - # http://arstechnica.com/apple/2007/10/mac-os-x-10-5/4/ - folder_type = "pre-Yosemite" -else: - print "Unknown OSX version(%s). Falling back to 10.10." % s - folder_type = "Yosemite" -template_folder = os.path.join(data_folder, "GenericFolderIcon.%s.iconset" % folder_type) - -convert_path = "convert" -iconutil_path = "iconutil" -seticon_path = os.path.join(data_folder, "lib", "seticon") - -cached_mask_suffix = ".mask" - - -################################################################ - - -def create_iconset(mask, temp_folder, iconset_folder, params): - global processes - - name, width, height, offset_center = params - - print "Generating %s image..." % name - - TEMP_MASK_IMAGE = os.path.join(temp_folder, "trimmed_%s.png" % name) - subprocess.check_call([ - convert_path, - mask, - "-trim", - "-resize", - ("%dx%d" % (width, height)), - "-bordercolor", "none", - "-border", str(10), - TEMP_MASK_IMAGE - ]) - - FILE_OUT = os.path.join(iconset_folder, "icon_%s.png" % name) - template_icon = os.path.join(template_folder, "icon_%s.png" % name) - - main_opacity = 15 - offset_white = 1 - opacity_white = 100 - - # Here comes the magic. - # TODO: rewrite in Python. - command = [ - convert_path, template_icon, "(", - "(", TEMP_MASK_IMAGE, "-negate", "-colorize", "3,23,40", "-negate", ")", - "(", - "(", - "(", - TEMP_MASK_IMAGE, - "(", - TEMP_MASK_IMAGE, "-negate", "-shadow", "100x1+10+0", "-geometry", "-2-2", - ")", - "-compose", "dst-out", "-composite", "+repage", - ")", - "(", - TEMP_MASK_IMAGE, - "(", - TEMP_MASK_IMAGE, "-negate", "-geometry", "+0-1", - ")", - "-compose", "dst-out", "-composite", "+repage", "-negate", "-geometry", ("+0+%d" % offset_white), - ")", - "-compose", "dissolve", "-define", ("compose:args=%dx50" % opacity_white), "-composite", "+repage", - ")", - "(", - TEMP_MASK_IMAGE, - "(", - TEMP_MASK_IMAGE, "-negate", "-geometry", "+0+1", - ")", - "-compose", "dst-out", "-composite", "+repage", - ")", - "-compose", "dissolve", "-define", "compose:args=50x80", "-composite", - ")", - "-compose", "dissolve", "-define", ("compose:args=60x%d" % main_opacity), "-composite", "+repage", - "-gravity", "Center", "-geometry", ("+0+%d" % offset_center), - "+repage", - ")", - "-compose", "over", "-composite", FILE_OUT - ] - - return subprocess.Popen(command) - - -################################################################ - - -def cache_path_for_target(target): - print args.cache_dir, target, ".mask" - return args.cache_dir + os.path.abspath(target) + ".mask" - -def process_mask(mask, target=None, add_to_cache=False): - print "" - print "Making icon file for %s" % mask - print "----------------" - - temp_folder = tempfile.mkdtemp() - - if (add_to_cache): - mask_cache_path = cache_path_for_target(target) - mask_cache_folder = os.path.dirname(mask_cache_path) - if not os.path.exists(mask_cache_folder): - os.makedirs(mask_cache_folder) - shutil.copyfile(mask, mask_cache_path) - - if target: - iconset_folder = os.path.join(temp_folder, "iconset.iconset") - icns_file = os.path.join(temp_folder, "icns.icns") - - os.mkdir(iconset_folder) - else: - root, _ = os.path.splitext(mask) - iconset_folder = root + ".iconset" - icns_file = root + ".icns" - - if not os.path.exists(iconset_folder): - os.mkdir(iconset_folder) - target = icns_file - - # mkdir -p "${ICONSET_FOLDER}" - - inputs = { - "Yosemite": [ - ["16x16", 12, 8, 1], ["16x16@2x", 26, 14, 2], - ["32x32", 26, 14, 2], ["32x32@2x", 52, 26, 2], - - ["128x128", 103, 53, 4], ["128x128@2x", 206, 106, 9], - ["256x256", 206, 106, 9], ["256x256@2x", 412, 212, 18], - ["512x512", 412, 212, 18], ["512x512@2x", 824, 424, 36] - ], - "pre-Yosemite": [ - ["16x16", 12, 8, 1], ["16x16@2x", 26, 14, 2], - ["32x32", 26, 14, 2], ["32x32@2x", 52, 60, 4], - - ["128x128", 103, 60, 9], ["128x128@2x", 206, 121, 18], - ["256x256", 206, 121, 18], ["256x256@2x", 412, 242, 36], - ["512x512", 412, 242, 36], ["512x512@2x", 824, 484, 72] - ] - } - - f = functools.partial(create_iconset, mask, temp_folder, iconset_folder) - processes = map(f, inputs[folder_type]) - - for process in processes: - process.wait() - - print "----------------" - print "Making the .icns file..." - - subprocess.check_call([ - iconutil_path, - "--convert", "icns", - "--output", icns_file, - iconset_folder - ]) - - # Set icon for target. - subprocess.check_call([ - seticon_path, - "-d", icns_file, - target - ]) - - # Reveal target. - if args.reveal: - subprocess.check_call([ - "open", - "-R", target - ]) - - # Clean up. - shutil.rmtree(temp_folder) - - print "----------------" - print "Done with %s: assigned to %s" % (mask, target) - -def target_for_cache_path(cache_path): - assert(cache_path.endswith(cached_mask_suffix)) - intermediate = cache_path[:-len(cached_mask_suffix)] - return os.path.join("/", os.path.relpath(intermediate, args.cache_dir)) - -def restore_from_cache(target): - mask_cache_path = cache_path_for_target(target) - print "Mask path from cache: %s" % mask_cache_path - process_mask( - mask_cache_path, - target=target, - add_to_cache=False - ) - -if args.mask: - if args.cache: - assert(args.target) - process_mask( - args.mask, - target=args.target, - add_to_cache=args.cache - ) -elif (args.restore_from_cache): - restore_from_cache(args.restore_from_cache) -elif (args.restore_all_from_cache): - for folder, _, files in os.walk(args.cache_dir): - for f in files: - if f.endswith(cached_mask_suffix): - cache_path = os.path.join(folder, f) - target = target_for_cache_path(cache_path) - if os.path.exists(target): - restore_from_cache(target) - else: - print "Target no longer exists: %s" % target -else: - parser.print_help() diff --git a/GenericFolderIcon.Yosemite.iconset/icon_128x128.png b/folderify/GenericFolderIcon.Yosemite.iconset/icon_128x128.png similarity index 100% rename from GenericFolderIcon.Yosemite.iconset/icon_128x128.png rename to folderify/GenericFolderIcon.Yosemite.iconset/icon_128x128.png diff --git a/GenericFolderIcon.Yosemite.iconset/icon_128x128@2x.png b/folderify/GenericFolderIcon.Yosemite.iconset/icon_128x128@2x.png similarity index 100% rename from GenericFolderIcon.Yosemite.iconset/icon_128x128@2x.png rename to folderify/GenericFolderIcon.Yosemite.iconset/icon_128x128@2x.png diff --git a/GenericFolderIcon.Yosemite.iconset/icon_16x16.png b/folderify/GenericFolderIcon.Yosemite.iconset/icon_16x16.png similarity index 100% rename from GenericFolderIcon.Yosemite.iconset/icon_16x16.png rename to folderify/GenericFolderIcon.Yosemite.iconset/icon_16x16.png diff --git a/GenericFolderIcon.Yosemite.iconset/icon_16x16@2x.png b/folderify/GenericFolderIcon.Yosemite.iconset/icon_16x16@2x.png similarity index 100% rename from GenericFolderIcon.Yosemite.iconset/icon_16x16@2x.png rename to folderify/GenericFolderIcon.Yosemite.iconset/icon_16x16@2x.png diff --git a/GenericFolderIcon.Yosemite.iconset/icon_256x256.png b/folderify/GenericFolderIcon.Yosemite.iconset/icon_256x256.png similarity index 100% rename from GenericFolderIcon.Yosemite.iconset/icon_256x256.png rename to folderify/GenericFolderIcon.Yosemite.iconset/icon_256x256.png diff --git a/GenericFolderIcon.Yosemite.iconset/icon_256x256@2x.png b/folderify/GenericFolderIcon.Yosemite.iconset/icon_256x256@2x.png similarity index 100% rename from GenericFolderIcon.Yosemite.iconset/icon_256x256@2x.png rename to folderify/GenericFolderIcon.Yosemite.iconset/icon_256x256@2x.png diff --git a/GenericFolderIcon.Yosemite.iconset/icon_32x32.png b/folderify/GenericFolderIcon.Yosemite.iconset/icon_32x32.png similarity index 100% rename from GenericFolderIcon.Yosemite.iconset/icon_32x32.png rename to folderify/GenericFolderIcon.Yosemite.iconset/icon_32x32.png diff --git a/GenericFolderIcon.Yosemite.iconset/icon_32x32@2x.png b/folderify/GenericFolderIcon.Yosemite.iconset/icon_32x32@2x.png similarity index 100% rename from GenericFolderIcon.Yosemite.iconset/icon_32x32@2x.png rename to folderify/GenericFolderIcon.Yosemite.iconset/icon_32x32@2x.png diff --git a/GenericFolderIcon.Yosemite.iconset/icon_512x512.png b/folderify/GenericFolderIcon.Yosemite.iconset/icon_512x512.png similarity index 100% rename from GenericFolderIcon.Yosemite.iconset/icon_512x512.png rename to folderify/GenericFolderIcon.Yosemite.iconset/icon_512x512.png diff --git a/GenericFolderIcon.Yosemite.iconset/icon_512x512@2x.png b/folderify/GenericFolderIcon.Yosemite.iconset/icon_512x512@2x.png similarity index 100% rename from GenericFolderIcon.Yosemite.iconset/icon_512x512@2x.png rename to folderify/GenericFolderIcon.Yosemite.iconset/icon_512x512@2x.png diff --git a/GenericFolderIcon.pre-Yosemite.iconset/icon_128x128.png b/folderify/GenericFolderIcon.pre-Yosemite.iconset/icon_128x128.png similarity index 100% rename from GenericFolderIcon.pre-Yosemite.iconset/icon_128x128.png rename to folderify/GenericFolderIcon.pre-Yosemite.iconset/icon_128x128.png diff --git a/GenericFolderIcon.pre-Yosemite.iconset/icon_128x128@2x.png b/folderify/GenericFolderIcon.pre-Yosemite.iconset/icon_128x128@2x.png similarity index 100% rename from GenericFolderIcon.pre-Yosemite.iconset/icon_128x128@2x.png rename to folderify/GenericFolderIcon.pre-Yosemite.iconset/icon_128x128@2x.png diff --git a/GenericFolderIcon.pre-Yosemite.iconset/icon_16x16.png b/folderify/GenericFolderIcon.pre-Yosemite.iconset/icon_16x16.png similarity index 100% rename from GenericFolderIcon.pre-Yosemite.iconset/icon_16x16.png rename to folderify/GenericFolderIcon.pre-Yosemite.iconset/icon_16x16.png diff --git a/GenericFolderIcon.pre-Yosemite.iconset/icon_16x16@2x.png b/folderify/GenericFolderIcon.pre-Yosemite.iconset/icon_16x16@2x.png similarity index 100% rename from GenericFolderIcon.pre-Yosemite.iconset/icon_16x16@2x.png rename to folderify/GenericFolderIcon.pre-Yosemite.iconset/icon_16x16@2x.png diff --git a/GenericFolderIcon.pre-Yosemite.iconset/icon_256x256.png b/folderify/GenericFolderIcon.pre-Yosemite.iconset/icon_256x256.png similarity index 100% rename from GenericFolderIcon.pre-Yosemite.iconset/icon_256x256.png rename to folderify/GenericFolderIcon.pre-Yosemite.iconset/icon_256x256.png diff --git a/GenericFolderIcon.pre-Yosemite.iconset/icon_256x256@2x.png b/folderify/GenericFolderIcon.pre-Yosemite.iconset/icon_256x256@2x.png similarity index 100% rename from GenericFolderIcon.pre-Yosemite.iconset/icon_256x256@2x.png rename to folderify/GenericFolderIcon.pre-Yosemite.iconset/icon_256x256@2x.png diff --git a/GenericFolderIcon.pre-Yosemite.iconset/icon_32x32.png b/folderify/GenericFolderIcon.pre-Yosemite.iconset/icon_32x32.png similarity index 100% rename from GenericFolderIcon.pre-Yosemite.iconset/icon_32x32.png rename to folderify/GenericFolderIcon.pre-Yosemite.iconset/icon_32x32.png diff --git a/GenericFolderIcon.pre-Yosemite.iconset/icon_32x32@2x.png b/folderify/GenericFolderIcon.pre-Yosemite.iconset/icon_32x32@2x.png similarity index 100% rename from GenericFolderIcon.pre-Yosemite.iconset/icon_32x32@2x.png rename to folderify/GenericFolderIcon.pre-Yosemite.iconset/icon_32x32@2x.png diff --git a/GenericFolderIcon.pre-Yosemite.iconset/icon_512x512.png b/folderify/GenericFolderIcon.pre-Yosemite.iconset/icon_512x512.png similarity index 100% rename from GenericFolderIcon.pre-Yosemite.iconset/icon_512x512.png rename to folderify/GenericFolderIcon.pre-Yosemite.iconset/icon_512x512.png diff --git a/GenericFolderIcon.pre-Yosemite.iconset/icon_512x512@2x.png b/folderify/GenericFolderIcon.pre-Yosemite.iconset/icon_512x512@2x.png similarity index 100% rename from GenericFolderIcon.pre-Yosemite.iconset/icon_512x512@2x.png rename to folderify/GenericFolderIcon.pre-Yosemite.iconset/icon_512x512@2x.png diff --git a/folderify/__init__.py b/folderify/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/folderify/__main__.py b/folderify/__main__.py new file mode 100644 index 0000000..26a969a --- /dev/null +++ b/folderify/__main__.py @@ -0,0 +1,319 @@ +#!/usr/bin/env python + +import argparse +import functools +import os.path +import platform +import shutil +import subprocess +import sys +import tempfile + +from string import Template + + +################################################################ + + +def main(): + + parser = argparse.ArgumentParser( + description="Generate a native OSX folder icon from a mask file.", + formatter_class=argparse.RawTextHelpFormatter + ) + + exclusive = parser.add_mutually_exclusive_group() + + exclusive.add_argument( + "mask", + action="store", + nargs="?", + type=str, + help="Mask image file. For best results:\n\ + - Use a .png mask.\n\ + - Use a solid black design over a transparent background.\n\ + - Make sure the corner pixels of the mask image are transparent. They are used for empty margins.\n\ + - Make sure the icon is at least around 1024x1024, in order to look good at maximum Retina resolution.") + + parser.add_argument( + "target", + action="store", + nargs="?", + type=str, + help="Target file or folder. \ + If a target is specified, the resulting icon will be applied to the target file/folder. \ + Else, a .iconset folder and .icns file will be created in the same folder as mask \ + (you can use \"Get Info\" in Finder to copy the icon from the .icns file).") + + parser.add_argument( + "--reveal", "-r", + action="store_true", + help="Reveal the target (or resulting .icns file) in Finder.") + + local_osx_version = ".".join(platform.mac_ver()[0].split(".")[:2]) + + parser.add_argument( + "--osx_version", "-x", + type=str, + default=local_osx_version, + help=("Version of the OSX folder icon, e.g. \"10.9\" or \"10.10\". \ + Defaults to the version this computer is running (%s)." % local_osx_version)) + + parser.add_argument( + "--cache", "-c", + action="store_true", + help="Cache the mask icon in the cache dir.") + + parser.add_argument( + "--cache-dir", + type=str, + default=os.path.expanduser("~/.folderify/cache"), + help="Cache directory.") + + exclusive.add_argument( + "--restore-from-cache", + metavar="PATH", + type=str, + help="Restore folderified icon to the file/folder at PATH,\ + using the mask image in the cache for that path.") + + exclusive.add_argument( + "--restore-all-from-cache", + action="store_true", + help="Restore all paths that have been cached.") + + + ################################################################ + + + args = parser.parse_args() + + if args.cache and not args.mask: + parser.error("Must specify mask in order to use --cache.") + + + ################################################################ + + data_folder = os.path.dirname(sys.modules[__name__].__file__) + + if args.osx_version == "10.10": + folder_type = "Yosemite" + elif args.osx_version in ["10.5", "10.6", "10.7", "10.8", "10.9"]: + # http://arstechnica.com/apple/2007/10/mac-os-x-10-5/4/ + folder_type = "pre-Yosemite" + else: + print "Unknown OSX version(%s). Falling back to 10.10." % s + folder_type = "Yosemite" + template_folder = os.path.join(data_folder, "GenericFolderIcon.%s.iconset" % folder_type) + + convert_path = "convert" + iconutil_path = "iconutil" + seticon_path = os.path.join(data_folder, "lib", "seticon") + + cached_mask_suffix = ".mask" + + + ################################################################ + + + def create_iconset(mask, temp_folder, iconset_folder, params): + global processes + + name, width, height, offset_center = params + + print "Generating %s image..." % name + + TEMP_MASK_IMAGE = os.path.join(temp_folder, "trimmed_%s.png" % name) + subprocess.check_call([ + convert_path, + mask, + "-trim", + "-resize", + ("%dx%d" % (width, height)), + "-bordercolor", "none", + "-border", str(10), + TEMP_MASK_IMAGE + ]) + + FILE_OUT = os.path.join(iconset_folder, "icon_%s.png" % name) + template_icon = os.path.join(template_folder, "icon_%s.png" % name) + + main_opacity = 15 + offset_white = 1 + opacity_white = 100 + + # Here comes the magic. + # TODO: rewrite in Python. + command = [ + convert_path, template_icon, "(", + "(", TEMP_MASK_IMAGE, "-negate", "-colorize", "3,23,40", "-negate", ")", + "(", + "(", + "(", + TEMP_MASK_IMAGE, + "(", + TEMP_MASK_IMAGE, "-negate", "-shadow", "100x1+10+0", "-geometry", "-2-2", + ")", + "-compose", "dst-out", "-composite", "+repage", + ")", + "(", + TEMP_MASK_IMAGE, + "(", + TEMP_MASK_IMAGE, "-negate", "-geometry", "+0-1", + ")", + "-compose", "dst-out", "-composite", "+repage", "-negate", "-geometry", ("+0+%d" % offset_white), + ")", + "-compose", "dissolve", "-define", ("compose:args=%dx50" % opacity_white), "-composite", "+repage", + ")", + "(", + TEMP_MASK_IMAGE, + "(", + TEMP_MASK_IMAGE, "-negate", "-geometry", "+0+1", + ")", + "-compose", "dst-out", "-composite", "+repage", + ")", + "-compose", "dissolve", "-define", "compose:args=50x80", "-composite", + ")", + "-compose", "dissolve", "-define", ("compose:args=60x%d" % main_opacity), "-composite", "+repage", + "-gravity", "Center", "-geometry", ("+0+%d" % offset_center), + "+repage", + ")", + "-compose", "over", "-composite", FILE_OUT + ] + + return subprocess.Popen(command) + + + ################################################################ + + + def cache_path_for_target(target): + print args.cache_dir, target, ".mask" + return args.cache_dir + os.path.abspath(target) + ".mask" + + def process_mask(mask, target=None, add_to_cache=False): + print "" + print "Making icon file for %s" % mask + print "----------------" + + temp_folder = tempfile.mkdtemp() + + if (add_to_cache): + mask_cache_path = cache_path_for_target(target) + mask_cache_folder = os.path.dirname(mask_cache_path) + if not os.path.exists(mask_cache_folder): + os.makedirs(mask_cache_folder) + shutil.copyfile(mask, mask_cache_path) + + if target: + iconset_folder = os.path.join(temp_folder, "iconset.iconset") + icns_file = os.path.join(temp_folder, "icns.icns") + + os.mkdir(iconset_folder) + else: + root, _ = os.path.splitext(mask) + iconset_folder = root + ".iconset" + icns_file = root + ".icns" + + if not os.path.exists(iconset_folder): + os.mkdir(iconset_folder) + target = icns_file + + # mkdir -p "${ICONSET_FOLDER}" + + inputs = { + "Yosemite": [ + ["16x16", 12, 8, 1], ["16x16@2x", 26, 14, 2], + ["32x32", 26, 14, 2], ["32x32@2x", 52, 26, 2], + + ["128x128", 103, 53, 4], ["128x128@2x", 206, 106, 9], + ["256x256", 206, 106, 9], ["256x256@2x", 412, 212, 18], + ["512x512", 412, 212, 18], ["512x512@2x", 824, 424, 36] + ], + "pre-Yosemite": [ + ["16x16", 12, 8, 1], ["16x16@2x", 26, 14, 2], + ["32x32", 26, 14, 2], ["32x32@2x", 52, 60, 4], + + ["128x128", 103, 60, 9], ["128x128@2x", 206, 121, 18], + ["256x256", 206, 121, 18], ["256x256@2x", 412, 242, 36], + ["512x512", 412, 242, 36], ["512x512@2x", 824, 484, 72] + ] + } + + f = functools.partial(create_iconset, mask, temp_folder, iconset_folder) + processes = map(f, inputs[folder_type]) + + for process in processes: + process.wait() + + print "----------------" + print "Making the .icns file..." + + subprocess.check_call([ + iconutil_path, + "--convert", "icns", + "--output", icns_file, + iconset_folder + ]) + + # Set icon for target. + subprocess.check_call([ + seticon_path, + "-d", icns_file, + target + ]) + + # Reveal target. + if args.reveal: + subprocess.check_call([ + "open", + "-R", target + ]) + + # Clean up. + shutil.rmtree(temp_folder) + + print "----------------" + print "Done with %s: assigned to %s" % (mask, target) + + def target_for_cache_path(cache_path): + assert(cache_path.endswith(cached_mask_suffix)) + intermediate = cache_path[:-len(cached_mask_suffix)] + return os.path.join("/", os.path.relpath(intermediate, args.cache_dir)) + + def restore_from_cache(target): + mask_cache_path = cache_path_for_target(target) + print "Mask path from cache: %s" % mask_cache_path + process_mask( + mask_cache_path, + target=target, + add_to_cache=False + ) + + if args.mask: + if args.cache: + assert(args.target) + process_mask( + args.mask, + target=args.target, + add_to_cache=args.cache + ) + elif (args.restore_from_cache): + restore_from_cache(args.restore_from_cache) + elif (args.restore_all_from_cache): + for folder, _, files in os.walk(args.cache_dir): + for f in files: + if f.endswith(cached_mask_suffix): + cache_path = os.path.join(folder, f) + target = target_for_cache_path(cache_path) + if os.path.exists(target): + restore_from_cache(target) + else: + print "Target no longer exists: %s" % target + else: + parser.print_help() + +__main__ = main + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/lib/osxiconutils.webloc b/folderify/lib/osxiconutils.webloc similarity index 100% rename from lib/osxiconutils.webloc rename to folderify/lib/osxiconutils.webloc diff --git a/lib/seticon b/folderify/lib/seticon similarity index 100% rename from lib/seticon rename to folderify/lib/seticon diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..d8e812a --- /dev/null +++ b/setup.py @@ -0,0 +1,70 @@ +from setuptools import setup, find_packages # Always prefer setuptools over distutils +from os import path + +# Get the long description from the relevant file +with open("README.md") as f: + long_description = f.read() + +setup( + name="folderify", + version="0.0.1", + description="A tool to generate pretty, beveled OSX folder icons.", + long_description=long_description, + url="https://github.com/lgarron/folderify", + + author="Lucas Garron", + author_email="code@garron.net", + + license="MIT", + + classifiers=[ + "Development Status :: 5 - Production/Stable", + + "Intended Audience :: Developers", + "Topic :: Multimedia :: Graphics", + "Topic :: Software Development :: Build Tools", + "Topic :: Software Development :: Libraries", + "Topic :: Utilities", + + "License :: OSI Approved :: MIT License", + + "Programming Language :: Python :: 2", + "Programming Language :: Python :: 2.6", + "Programming Language :: Python :: 2.7", + # "Programming Language :: Python :: 3", + # "Programming Language :: Python :: 3.2", + # "Programming Language :: Python :: 3.3", + # "Programming Language :: Python :: 3.4", + ], + + # # What does your project relate to? + keywords="icon OSX Mac Darwin graphics folder imagemagick", + + # If there are data files included in your packages that need to be + # installed, specify them here. If using Python 2.6 or less, then these + # have to be included in MANIFEST.in as well. + package_data={ + "folderify": [ + "GenericFolderIcon.pre-Yosemite.iconset/*.png", + "GenericFolderIcon.Yosemite.iconset/*.png", + "lib/seticon", + ] + }, + + packages=[ + "folderify" + ], + package_dir={ + "folderify": "folderify" + }, + + + # To provide executable scripts, use entry points in preference to the + # "scripts" keyword. Entry points provide cross-platform support and allow + # pip to create the appropriate form of executable for the target platform. + entry_points={ + "console_scripts": [ + "folderify = folderify.folderify:main", + ], + }, +) \ No newline at end of file