summaryrefslogtreecommitdiffstats
path: root/packaging
diff options
context:
space:
mode:
authorCalum Lind <calumlind+deluge@gmail.com>2015-08-24 12:39:25 +0100
committerCalum Lind <calumlind+deluge@gmail.com>2015-08-24 15:35:25 +0100
commit1c3e14919f41cac16df3909bc1ef07252e58b6f6 (patch)
tree7bbb94bb1fee3aa25fcbea9d3daf2a68777eaedd /packaging
parent0ee8c7d70f54af976bac772eba937c83a2968718 (diff)
downloaddeluge-1c3e14919f41cac16df3909bc1ef07252e58b6f6.tar.gz
deluge-1c3e14919f41cac16df3909bc1ef07252e58b6f6.tar.bz2
deluge-1c3e14919f41cac16df3909bc1ef07252e58b6f6.zip
[Win32] Refactor bbreeze script
* In setup.py put web and deluged back into console_script as the gtkui hack in bbfreeze is a windows only issue for popup cmd windows showing. * Altered the bbreeze script to find any deluge scripts in pythonpath. * Use setIcon now in bbfreeze and use icon from package. * Use version stamp from pywin32.
Diffstat (limited to 'packaging')
-rw-r--r--packaging/win32/VersionInfo.py292
-rw-r--r--packaging/win32/deluge-bbfreeze.py137
-rw-r--r--packaging/win32/deluge.icobin25214 -> 0 bytes
-rw-r--r--packaging/win32/icon.py205
4 files changed, 81 insertions, 553 deletions
diff --git a/packaging/win32/VersionInfo.py b/packaging/win32/VersionInfo.py
deleted file mode 100644
index fbbc9eb91..000000000
--- a/packaging/win32/VersionInfo.py
+++ /dev/null
@@ -1,292 +0,0 @@
-# -*- coding: latin-1 -*-
-##
-## Copyright (c) 2000-2013 Thomas Heller
-##
-## Permission is hereby granted, free of charge, to any person obtaining
-## a copy of this software and associated documentation files (the
-## "Software"), to deal in the Software without restriction, including
-## without limitation the rights to use, copy, modify, merge, publish,
-## distribute, sublicense, and/or sell copies of the Software, and to
-## permit persons to whom the Software is furnished to do so, subject to
-## the following conditions:
-##
-## The above copyright notice and this permission notice shall be
-## included in all copies or substantial portions of the Software.
-##
-## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-## EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-## MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-## LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-## OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-## WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-##
-
-#
-# $Id: VersionInfo.py 738 2013-09-07 10:11:45Z theller $
-#
-# $Log$
-# Revision 1.3 2004/01/16 10:45:31 theller
-# Move py2exe from the sandbox directory up to the root dir.
-#
-# Revision 1.3 2003/12/29 13:44:57 theller
-# Adapt for Python 2.3.
-#
-# Revision 1.2 2003/09/18 20:19:57 theller
-# Remove a 2.3 warning, but mostly this checkin is to test the brand new
-# py2exe-checkins mailing list.
-#
-# Revision 1.1 2003/08/29 12:30:52 mhammond
-# New py2exe now uses the old resource functions :)
-#
-# Revision 1.1 2002/01/29 09:30:55 theller
-# version 0.3.0
-#
-# Revision 1.2 2002/01/14 19:08:05 theller
-# Better (?) Unicode handling.
-#
-# Revision 1.1 2002/01/07 10:30:32 theller
-# Create a version resource.
-#
-#
-import struct
-
-VOS_NT_WINDOWS32 = 0x00040004
-VFT_APP = 0x00000001
-
-RT_VERSION = 16
-
-class VersionError(Exception):
- pass
-
-def w32_uc(text):
- """convert a string into unicode, then encode it into UTF-16
- little endian, ready to use for win32 apis"""
- if type(text) is str:
- return unicode(text, "unicode-escape").encode("utf-16-le")
- return unicode(text).encode("utf-16-le")
-
-class VS_FIXEDFILEINFO:
- dwSignature = 0xFEEF04BDL
- dwStrucVersion = 0x00010000
- dwFileVersionMS = 0x00010000
- dwFileVersionLS = 0x00000001
- dwProductVersionMS = 0x00010000
- dwProductVersionLS = 0x00000001
- dwFileFlagsMask = 0x3F
- dwFileFlags = 0
- dwFileOS = VOS_NT_WINDOWS32
- dwFileType = VFT_APP
- dwFileSubtype = 0
- dwFileDateMS = 0
- dwFileDateLS = 0
-
- fmt = "13L"
-
- def __init__(self, version):
- import string
- version = string.replace(version, ",", ".")
- fields = string.split(version + '.0.0.0.0', ".")[:4]
- fields = map(string.strip, fields)
- try:
- self.dwFileVersionMS = int(fields[0]) * 65536 + int(fields[1])
- self.dwFileVersionLS = int(fields[2]) * 65536 + int(fields[3])
- except ValueError:
- raise VersionError("could not parse version number '%s'" % version)
-
- def __str__(self):
- return struct.pack(self.fmt,
- self.dwSignature,
- self.dwStrucVersion,
- self.dwFileVersionMS,
- self.dwFileVersionLS,
- self.dwProductVersionMS,
- self.dwProductVersionLS,
- self.dwFileFlagsMask,
- self.dwFileFlags,
- self.dwFileOS,
- self.dwFileType,
- self.dwFileSubtype,
- self.dwFileDateMS,
- self.dwFileDateLS)
-
-def align(data):
- pad = - len(data) % 4
- return data + '\000' * pad
-
-class VS_STRUCT:
- items = ()
-
- def __str__(self):
- szKey = w32_uc(self.name)
- ulen = len(szKey)+2
-
- value = self.get_value()
- data = struct.pack("h%ss0i" % ulen, self.wType, szKey) + value
-
- data = align(data)
-
- for item in self.items:
- data = data + str(item)
-
- wLength = len(data) + 4 # 4 bytes for wLength and wValueLength
- wValueLength = len(value)
-
- return self.pack("hh", wLength, wValueLength, data)
-
- def pack(self, fmt, len, vlen, data):
- return struct.pack(fmt, len, vlen) + data
-
- def get_value(self):
- return ""
-
-
-class String(VS_STRUCT):
- wType = 1
- items = ()
-
- def __init__(self, name_value):
- (name, value) = name_value
- self.name = name
- if value:
- self.value = value + '\000' # strings must be zero terminated
- else:
- self.value = value
-
- def pack(self, fmt, len, vlen, data):
- # ValueLength is measured in WORDS, not in BYTES!
- return struct.pack(fmt, len, vlen/2) + data
-
- def get_value(self):
- return w32_uc(self.value)
-
-
-class StringTable(VS_STRUCT):
- wType = 1
-
- def __init__(self, name, strings):
- self.name = name
- self.items = map(String, strings)
-
-
-class StringFileInfo(VS_STRUCT):
- wType = 1
- name = "StringFileInfo"
-
- def __init__(self, name, strings):
- self.items = [StringTable(name, strings)]
-
-class Var(VS_STRUCT):
- # MSDN says:
- # If you use the Var structure to list the languages your
- # application or DLL supports instead of using multiple version
- # resources, use the Value member to contain an array of DWORD
- # values indicating the language and code page combinations
- # supported by this file. The low-order word of each DWORD must
- # contain a Microsoft language identifier, and the high-order word
- # must contain the IBM® code page number. Either high-order or
- # low-order word can be zero, indicating that the file is language
- # or code page independent. If the Var structure is omitted, the
- # file will be interpreted as both language and code page
- # independent.
- wType = 0
- name = "Translation"
-
- def __init__(self, value):
- self.value = value
-
- def get_value(self):
- return struct.pack("l", self.value)
-
-class VarFileInfo(VS_STRUCT):
- wType = 1
- name = "VarFileInfo"
-
- def __init__(self, *names):
- self.items = map(Var, names)
-
- def get_value(self):
- return ""
-
-class VS_VERSIONINFO(VS_STRUCT):
- wType = 0 # 0: binary data, 1: text data
- name = "VS_VERSION_INFO"
-
- def __init__(self, version, items):
- self.value = VS_FIXEDFILEINFO(version)
- self.items = items
-
- def get_value(self):
- return str(self.value)
-
-class Version(object):
- def __init__(self,
- version,
- comments = None,
- company_name = None,
- file_description = None,
- internal_name = None,
- legal_copyright = None,
- legal_trademarks = None,
- original_filename = None,
- private_build = None,
- product_name = None,
- product_version = None,
- special_build = None):
- self.version = version
- strings = []
- if comments is not None:
- strings.append(("Comments", comments))
- if company_name is not None:
- strings.append(("CompanyName", company_name))
- if file_description is not None:
- strings.append(("FileDescription", file_description))
- strings.append(("FileVersion", version))
- if internal_name is not None:
- strings.append(("InternalName", internal_name))
- if legal_copyright is not None:
- strings.append(("LegalCopyright", legal_copyright))
- if legal_trademarks is not None:
- strings.append(("LegalTrademarks", legal_trademarks))
- if original_filename is not None:
- strings.append(("OriginalFilename", original_filename))
- if private_build is not None:
- strings.append(("PrivateBuild", private_build))
- if product_name is not None:
- strings.append(("ProductName", product_name))
- strings.append(("ProductVersion", product_version or version))
- if special_build is not None:
- strings.append(("SpecialBuild", special_build))
- self.strings = strings
-
- def resource_bytes(self):
- vs = VS_VERSIONINFO(self.version,
- [StringFileInfo("040904B0",
- self.strings),
- VarFileInfo(0x04B00409)])
- return str(vs)
-
-def test():
- import sys
- sys.path.append("c:/tmp")
- from hexdump import hexdump
- version = Version("1, 0, 0, 1",
- comments = "ümläut comments",
- company_name = "No Company",
- file_description = "silly application",
- internal_name = "silly",
- legal_copyright = u"Copyright © 2003",
-## legal_trademark = "",
- original_filename = "silly.exe",
- private_build = "test build",
- product_name = "silly product",
- product_version = None,
-## special_build = ""
- )
- hexdump(version.resource_bytes())
-
-if __name__ == '__main__':
- import sys
- sys.path.append("d:/nbalt/tmp")
- from hexdump import hexdump
- test()
diff --git a/packaging/win32/deluge-bbfreeze.py b/packaging/win32/deluge-bbfreeze.py
index 7b2d2f0e3..a9f834e32 100644
--- a/packaging/win32/deluge-bbfreeze.py
+++ b/packaging/win32/deluge-bbfreeze.py
@@ -1,35 +1,56 @@
import glob
import os
+import re
import shutil
import sys
-import bbfreeze.recipes
+import bbfreeze
import gtk
import icon
import win32api
-from bbfreeze import Freezer
-from VersionInfo import Version
+from win32verstamp import stamp
import deluge.common
-# Get build_version from installed deluge
+class VersionInfo(object):
+ def __init__(self, version, internalName = None, originalFileName = None,
+ comments = None, company = None, description = None,
+ copyright = None, trademarks = None, product = None, dll = False,
+ debug = False, verbose = True):
+ parts = version.split(".")
+ while len(parts) < 4:
+ parts.append("0")
+ self.version = ".".join(parts)
+ self.internal_name = internalName
+ self.original_filename = originalFileName
+ self.comments = comments
+ self.company = company
+ self.description = description
+ self.copyright = copyright
+ self.trademarks = trademarks
+ self.product = product
+ self.dll = dll
+ self.debug = debug
+ self.verbose = verbose
+
+# Get build_version from installed deluge.
build_version = deluge.common.get_version()
print "Deluge Version: %s" % build_version
+
python_path = os.path.dirname(sys.executable)
if python_path.endswith("Scripts"):
python_path = python_path[:-8]
python_path += os.path.sep
-
print "Python Path: %s" % python_path
-gtk_root = os.path.join(gtk.__path__[0], "..\\runtime\\")
-# Include python modules not picked up automatically by bbfreeze
+gtk_root = os.path.join(gtk.__path__[0], "..", "runtime") + os.path.sep
+
+# Include python modules not picked up automatically by bbfreeze.
includes = ("libtorrent", "cairo", "pangocairo", "atk", "pango", "twisted.internet.utils",
"gio", "gzip", "email.mime.multipart", "email.mime.text", "_cffi_backend")
excludes = ("numpy", "OpenGL", "psyco", "win32ui")
-dst = "..\\build-win32\\deluge-bbfreeze-" + build_version + "\\"
-
+build_dir = "..\\build-win32\\deluge-bbfreeze-" + build_version + "\\"
# Need to override bbfreeze function so that it includes all gtk libraries
# in the installer so users don't require a separate GTK+ installation.
@@ -37,55 +58,58 @@ def recipe_gtk_override(mf):
return True
bbfreeze.recipes.recipe_gtk_and_friends = recipe_gtk_override
-f = Freezer(dst, includes=includes, excludes=excludes)
-f.include_py = False
-# Can/should we grab this from setup.py entry_points somehow
-gui_scripts = ["deluge", "deluged", "deluge-web", "deluge-gtk"]
-console_scripts = ["deluge-debug", "deluged-debug", "deluge-web-debug", "deluge-console"]
-
-# Copy the scripts to get rid of the '-script' suffix before adding to freezer
-for script in gui_scripts:
- shutil.copy(python_path + "Scripts/%s-script.pyw" % script, python_path + "Scripts/%s.pyw" % script)
- f.addScript(python_path + "Scripts/%s.pyw" % script, gui_only=True)
-for script in console_scripts:
- shutil.copy(python_path + "Scripts/%s-script.py" % script, python_path + "Scripts/%s.py" % script)
- f.addScript(python_path + "Scripts/%s.py" % script, gui_only=False)
-f() # starts the freezing process
-
-# Clean up the duplicated scripts
-for script in gui_scripts:
- os.remove(python_path + "Scripts/%s.pyw" % script)
-for script in console_scripts:
- os.remove(python_path + "Scripts/%s.py" % script)
-
-# add icons to the exe files
-icon_path = os.path.join(os.path.dirname(__file__), "deluge.ico")
-for script in console_scripts + gui_scripts:
- icon.CopyIcons(dst + script + ".exe", icon_path)
+fzr = bbfreeze.Freezer(build_dir, includes=includes, excludes=excludes)
+fzr.include_py = False
+fzr.setIcon(os.path.join(os.path.dirname(deluge.common.__file__), "ui", "data", "pixmaps", "deluge.ico"))
+
+# TODO: Can/should we grab the script list from setup.py entry_points somehow.
+
+# Hide cmd console popup for these console entries force gui_script True.
+force_gui = ["deluge-web", "deluged", "deluge-console"]
+script_list = []
+for script in glob.glob(python_path + "Scripts\\deluge*-script.py*"):
+ # Copy the scripts to remove the '-script' suffix before adding to freezer.
+ new_script = script.replace("-script", "")
+ shutil.copy(script, new_script)
+
+ script_splitext = os.path.splitext(os.path.basename(new_script))
+ if script_splitext[1] == "pyw" or script_splitext[0] in force_gui:
+ gui_script = True
+ else:
+ gui_script = False
+ try:
+ fzr.addScript(new_script, gui_only=gui_script)
+
+ script_list.append(new_script)
+ except:
+ os.remove(script)
+
+# Start the freezing process.
+fzr()
+
+# Clean up the duplicated scripts.
+for script in script_list:
+ os.remove(script)
# Add version information to exe files.
-for script in console_scripts + gui_scripts:
- script_exe = script + ".exe"
- version = Version(build_version,
- file_description="Deluge Bittorrent Client",
- company_name="Deluge Team",
- legal_copyright="GPLv3",
- original_filename=script_exe,
- product_name="Deluge",
- product_version=build_version)
-
- pyhandle = win32api.BeginUpdateResource(os.path.join(dst, script_exe), 0)
- win32api.UpdateResource(pyhandle, 16, 1, version.resource_bytes())
- win32api.EndUpdateResource(pyhandle, 0)
-
-# exclude files which are already included in GTK or Windows
+for script in script_list:
+ script_exe = os.path.splitext(os.path.basename(script))[0] + ".exe"
+ if not re.search('[a-zA-Z_-]', build_version):
+ versionInfo = VersionInfo(build_version,
+ description="Deluge Bittorrent Client",
+ company="Deluge Team",
+ product="Deluge",
+ copyright="GPLv3")
+ stamp(os.path.join(build_dir, script_exe), versionInfo)
+
+# Exclude files which are already included in GTK or Windows.
excludeDlls = ("MSIMG32.dll", "MSVCR90.dll", "MSVCP90.dll", "POWRPROF.dll", "DNSAPI.dll", "USP10.dll")
-for file in excludeDlls:
- for filename in glob.glob(dst + file):
+for dll in excludeDlls:
+ for filename in glob.glob(os.path.join(build_dir, dll)):
print "removing file:", filename
os.remove(filename)
-# copy gtk locale files
+# Copy gtk locale files.
gtk_locale = os.path.join(gtk_root, 'share/locale')
locale_include_list = ['gtk20.mo', 'locale.alias']
@@ -96,9 +120,9 @@ def ignored_files(adir, filenames):
if not os.path.isdir(os.path.join(adir, filename))
and filename not in locale_include_list
]
-shutil.copytree(gtk_locale, os.path.join(dst, 'share/locale'), ignore=ignored_files)
+shutil.copytree(gtk_locale, os.path.join(build_dir, 'share/locale'), ignore=ignored_files)
-# copy gtk theme files
+# Copy gtk theme files.
theme_include_list = [
[gtk_root, "share/icons/hicolor/index.theme"],
[gtk_root, "lib/gtk-2.0/2.10.0/engines"],
@@ -110,15 +134,16 @@ theme_include_list = [
for path_root, path in theme_include_list:
full_path = os.path.join(path_root, path)
if os.path.isdir(full_path):
- shutil.copytree(full_path, os.path.join(dst, path))
+ shutil.copytree(full_path, os.path.join(build_dir, path))
else:
- dst_dir = os.path.join(dst, os.path.dirname(path))
+ dst_dir = os.path.join(build_dir, os.path.dirname(path))
try:
os.makedirs(dst_dir)
except:
pass
shutil.copy(full_path, dst_dir)
+# Copy version info to file for nsis script.
file = open('VERSION.tmp', 'w')
file.write("build_version = \"%s\"" % build_version)
file.close()
diff --git a/packaging/win32/deluge.ico b/packaging/win32/deluge.ico
deleted file mode 100644
index ef5c3dd34..000000000
--- a/packaging/win32/deluge.ico
+++ /dev/null
Binary files differ
diff --git a/packaging/win32/icon.py b/packaging/win32/icon.py
deleted file mode 100644
index 7563a22f5..000000000
--- a/packaging/win32/icon.py
+++ /dev/null
@@ -1,205 +0,0 @@
-#! /usr/bin/env python
-# Copyright (C) 2005, Giovanni Bajo
-# Based on previous work under copyright (c) 2002 McMillan Enterprises, Inc.
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
-
-# This code is courtesy of Thomas Heller, who
-# has kindly donated it to this project.
-RT_ICON = 3
-RT_GROUP_ICON = 14
-LOAD_LIBRARY_AS_DATAFILE = 2
-
-import struct
-import types
-
-try:
- StringTypes = types.StringTypes
-except AttributeError:
- StringTypes = [type("")]
-
-
-class Structure:
- def __init__(self):
- size = self._sizeInBytes = struct.calcsize(self._format_)
- self._fields_ = list(struct.unpack(self._format_, '\000' * size))
- indexes = self._indexes_ = {}
- for i in range(len(self._names_)):
- indexes[self._names_[i]] = i
-
- def dump(self):
- # print "I: DUMP of", self
- for name in self._names_:
- if name[0] != '_':
- # print "I: %20s = %s" % (name, getattr(self, name))
- pass
-
- def __getattr__(self, name):
- if name in self._names_:
- index = self._indexes_[name]
- return self._fields_[index]
- try:
- return self.__dict__[name]
- except KeyError:
- raise AttributeError(name)
-
- def __setattr__(self, name, value):
- if name in self._names_:
- index = self._indexes_[name]
- self._fields_[index] = value
- else:
- self.__dict__[name] = value
-
- def tostring(self):
- return apply(struct.pack, [self._format_, ] + self._fields_)
-
- def fromfile(self, file):
- data = file.read(self._sizeInBytes)
- self._fields_ = list(struct.unpack(self._format_, data))
-
-
-class ICONDIRHEADER(Structure):
- _names_ = "idReserved", "idType", "idCount"
- _format_ = "hhh"
-
-
-class ICONDIRENTRY(Structure):
- _names_ = "bWidth", "bHeight", "bColorCount", "bReserved", "wPlanes", "wBitCount", "dwBytesInRes", "dwImageOffset"
- _format_ = "bbbbhhii"
-
-
-class GRPICONDIR(Structure):
- _names_ = "idReserved", "idType", "idCount"
- _format_ = "hhh"
-
-
-class GRPICONDIRENTRY(Structure):
- _names_ = "bWidth", "bHeight", "bColorCount", "bReserved", "wPlanes", "wBitCount", "dwBytesInRes", "nID"
- _format_ = "bbbbhhih"
-
-
-class IconFile:
- def __init__(self, path):
- self.path = path
- file = open(path, "rb")
- self.entries = []
- self.images = []
- header = self.header = ICONDIRHEADER()
- header.fromfile(file)
- for i in range(header.idCount):
- entry = ICONDIRENTRY()
- entry.fromfile(file)
- self.entries.append(entry)
- for e in self.entries:
- file.seek(e.dwImageOffset, 0)
- self.images.append(file.read(e.dwBytesInRes))
-
- def grp_icon_dir(self):
- return self.header.tostring()
-
- def grp_icondir_entries(self, id=1):
- data = ""
- for entry in self.entries:
- e = GRPICONDIRENTRY()
- for n in e._names_[:-1]:
- setattr(e, n, getattr(entry, n))
- e.nID = id
- id = id + 1
- data = data + e.tostring()
- return data
-
-
-def CopyIcons_FromIco(dstpath, srcpath, id=1): # NOQA
- import win32api
- icons = map(IconFile, srcpath)
- print "I: Updating icons from", srcpath, "to", dstpath
-
- hdst = win32api.BeginUpdateResource(dstpath, 0)
-
- iconid = 1
- for i in range(len(icons)):
- f = icons[i]
- data = f.grp_icon_dir()
- data = data + f.grp_icondir_entries(iconid)
- win32api.UpdateResource(hdst, RT_GROUP_ICON, i, data)
- # print "I: Writing RT_GROUP_ICON %d resource with %d bytes" % (i, len(data))
- for data in f.images:
- win32api.UpdateResource(hdst, RT_ICON, iconid, data)
- # print "I: Writing RT_ICON %d resource with %d bytes" % (iconid, len(data))
- iconid = iconid + 1
-
- win32api.EndUpdateResource(hdst, 0)
-
-
-def CopyIcons(dstpath, srcpath): # NOQA
- import os.path
- import string
-
- if type(srcpath) in StringTypes:
- srcpath = [srcpath]
-
- def splitter(s):
- try:
- srcpath, index = map(string.strip, string.split(s, ','))
- return srcpath, int(index)
- except ValueError:
- return s, None
-
- srcpath = map(splitter, srcpath)
- # print "I: SRCPATH", srcpath
-
- if len(srcpath) > 1:
- # At the moment, we support multiple icons only from .ico files
- srcs = []
- for s in srcpath:
- e = os.path.splitext(s[0])[1]
- if string.lower(e) != '.ico':
- raise ValueError("multiple icons supported only from .ico files")
- if s[1] is not None:
- raise ValueError("index not allowed for .ico files")
- srcs.append(s[0])
- return CopyIcons_FromIco(dstpath, srcs)
-
- srcpath, index = srcpath[0]
- srcext = os.path.splitext(srcpath)[1]
- if string.lower(srcext) == '.ico':
- return CopyIcons_FromIco(dstpath, [srcpath])
- if index is not None:
- print "I: Updating icons from", srcpath, ", %d to" % index, dstpath
- else:
- print "I: Updating icons from", srcpath, "to", dstpath
- import win32api
- hdst = win32api.BeginUpdateResource(dstpath, 0)
- hsrc = win32api.LoadLibraryEx(srcpath, 0, LOAD_LIBRARY_AS_DATAFILE)
- if index is None:
- grpname = win32api.EnumResourceNames(hsrc, RT_GROUP_ICON)[0]
- elif index >= 0:
- grpname = win32api.EnumResourceNames(hsrc, RT_GROUP_ICON)[index]
- else:
- grpname = -index
- data = win32api.LoadResource(hsrc, RT_GROUP_ICON, grpname)
- win32api.UpdateResource(hdst, RT_GROUP_ICON, grpname, data)
- for iconname in win32api.EnumResourceNames(hsrc, RT_ICON):
- data = win32api.LoadResource(hsrc, RT_ICON, iconname)
- win32api.UpdateResource(hdst, RT_ICON, iconname, data)
- win32api.FreeLibrary(hsrc)
- win32api.EndUpdateResource(hdst, 0)
-
-if __name__ == "__main__":
- import sys
-
- dstpath = sys.argv[1]
- srcpath = sys.argv[2:]
- CopyIcons(dstpath, srcpath)