Rev 3626: (Mark Hammond) Updates to setup.py to support bundling tortoisebzr in file:///home/pqm/archives/thelove/bzr/%2Btrunk/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Thu Aug 14 04:23:31 BST 2008


At file:///home/pqm/archives/thelove/bzr/%2Btrunk/

------------------------------------------------------------
revno: 3626
revision-id: pqm at pqm.ubuntu.com-20080814032324-mhfk4rggo7hgxeuf
parent: pqm at pqm.ubuntu.com-20080813232540-mgtcd9chtkd9kda0
parent: mhammond at skippinet.com.au-20080814014130-ohoxsrqy94jldajv
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Thu 2008-08-14 04:23:24 +0100
message:
  (Mark Hammond) Updates to setup.py to support bundling tortoisebzr
  	and qbzr into the standalone win32 installer.
modified:
  setup.py                       setup.py-20050314065409-02f8a0a6e3f9bc70
  tools/win32/bzr.iss.cog        bzr.iss.cog-20060622100836-b3yup582rt3y0nvm-5
    ------------------------------------------------------------
    revno: 3565.5.9
    revision-id: mhammond at skippinet.com.au-20080814014130-ohoxsrqy94jldajv
    parent: mhammond at skippinet.com.au-20080813233916-co6sjx89hnu9pgfe
    committer: Mark Hammond <mhammond at skippinet.com.au>
    branch nick: bzr.work.win32binary.tbzr-setup
    timestamp: Thu 2008-08-14 11:41:30 +1000
    message:
      Address John's review comments
    modified:
      setup.py                       setup.py-20050314065409-02f8a0a6e3f9bc70
      tools/win32/bzr.iss.cog        bzr.iss.cog-20060622100836-b3yup582rt3y0nvm-5
    ------------------------------------------------------------
    revno: 3565.5.8
    revision-id: mhammond at skippinet.com.au-20080813233916-co6sjx89hnu9pgfe
    parent: mhammond at skippinet.com.au-20080810111639-9upz1wig1s8lvz62
    committer: Mark Hammond <mhammond at skippinet.com.au>
    branch nick: bzr.work.win32binary.tbzr-setup
    timestamp: Thu 2008-08-14 09:39:16 +1000
    message:
      s/TBZR/Tortoise/ in the Inno status messages.
    modified:
      tools/win32/bzr.iss.cog        bzr.iss.cog-20060622100836-b3yup582rt3y0nvm-5
    ------------------------------------------------------------
    revno: 3565.5.7
    revision-id: mhammond at skippinet.com.au-20080810111639-9upz1wig1s8lvz62
    parent: mhammond at skippinet.com.au-20080731070112-aafagt2n4lax4977
    committer: Mark Hammond <mhammond at skippinet.com.au>
    branch nick: bzr.work.win32binary.tbzr-setup
    timestamp: Sun 2008-08-10 21:16:39 +1000
    message:
      install all files with 'restartreplace uninsrestartdelete' and close
      tbzrcache at uninstall time.
    modified:
      tools/win32/bzr.iss.cog        bzr.iss.cog-20060622100836-b3yup582rt3y0nvm-5
    ------------------------------------------------------------
    revno: 3565.5.6
    revision-id: mhammond at skippinet.com.au-20080731070112-aafagt2n4lax4977
    parent: mhammond at skippinet.com.au-20080731065534-n0jl9z7sim2lj36z
    committer: Mark Hammond <mhammond at skippinet.com.au>
    branch nick: bzr.work.win32binary.tbzr-setup
    timestamp: Thu 2008-07-31 17:01:12 +1000
    message:
      move tbzr and qbzr py2exe config code into their own functions.
    modified:
      setup.py                       setup.py-20050314065409-02f8a0a6e3f9bc70
    ------------------------------------------------------------
    revno: 3565.5.5
    revision-id: mhammond at skippinet.com.au-20080731065534-n0jl9z7sim2lj36z
    parent: mhammond at skippinet.com.au-20080731053858-rzby1lwoufgoocww
    committer: Mark Hammond <mhammond at skippinet.com.au>
    branch nick: bzr.work.win32binary.tbzr-setup
    timestamp: Thu 2008-07-31 16:55:34 +1000
    message:
      paramiko has applied a patch making win32ui unnecessary and the wiki has
      been updated with the defails, so checking for that dll can be removed.
    modified:
      tools/win32/bzr.iss.cog        bzr.iss.cog-20060622100836-b3yup582rt3y0nvm-5
    ------------------------------------------------------------
    revno: 3565.5.4
    revision-id: mhammond at skippinet.com.au-20080731053858-rzby1lwoufgoocww
    parent: mhammond at skippinet.com.au-20080731053215-3cu1wwxigtyu1kml
    committer: Mark Hammond <mhammond at skippinet.com.au>
    branch nick: bzr.work.win32binary.tbzr-setup
    timestamp: Thu 2008-07-31 15:38:58 +1000
    message:
      byte-compile plugins; tweaks so qbzr and bzrsvn can be packaged.
    modified:
      setup.py                       setup.py-20050314065409-02f8a0a6e3f9bc70
    ------------------------------------------------------------
    revno: 3565.5.3
    revision-id: mhammond at skippinet.com.au-20080731053215-3cu1wwxigtyu1kml
    parent: mhammond at skippinet.com.au-20080722105302-027b8v2xx2ts1iai
    parent: pqm at pqm.ubuntu.com-20080730213059-hcremsawwvcqjcj1
    committer: Mark Hammond <mhammond at skippinet.com.au>
    branch nick: bzr.work.win32binary.tbzr-setup
    timestamp: Thu 2008-07-31 15:32:15 +1000
    message:
      merge
    added:
      doc/developers/ppa.txt         ppa.txt-20080722055539-606u7t2z32t3ae4w-1
    modified:
      NEWS                           NEWS-20050323055033-4e00b5db738777ff
      bzrlib/_dirstate_helpers_py.py _dirstate_helpers_py-20070710145033-90nz6cqglsk150jy-1
      bzrlib/_patiencediff_py.py     cdvdifflib.py-20051106064558-f8f8097fbf0db4e4
      bzrlib/branch.py               branch.py-20050309040759-e4baf4e0d046576e
      bzrlib/branchbuilder.py        branchbuilder.py-20070427022007-zlxpqz2lannhk6y8-1
      bzrlib/builtins.py             builtins.py-20050830033751-fc01482b9ca23183
      bzrlib/bzrdir.py               bzrdir.py-20060131065624-156dfea39c4387cb
      bzrlib/check.py                check.py-20050309040759-f3a679400c06bcc1
      bzrlib/dirstate.py             dirstate.py-20060728012006-d6mvoihjb3je9peu-1
      bzrlib/errors.py               errors.py-20050309040759-20512168c4e14fbd
      bzrlib/export/dir_exporter.py  dir_exporter.py-20051114235828-b51397f56bc7b117
      bzrlib/export/tar_exporter.py  tar_exporter.py-20051114235828-1f6349a2f090a5d0
      bzrlib/export/zip_exporter.py  zip_exporter.py-20051114235828-8f57f954fba6497e
      bzrlib/fetch.py                fetch.py-20050818234941-26fea6105696365d
      bzrlib/inventory.py            inventory.py-20050309040759-6648b84ca2005b37
      bzrlib/merge_directive.py      merge_directive.py-20070228184838-ja62280spt1g7f4x-1
      bzrlib/osutils.py              osutils.py-20050309040759-eeaff12fbf77ac86
      bzrlib/remote.py               remote.py-20060720103555-yeeg2x51vn0rbtdp-1
      bzrlib/repofmt/knitrepo.py     knitrepo.py-20070206081537-pyy4a00xdas0j4pf-1
      bzrlib/repofmt/pack_repo.py    pack_repo.py-20070813041115-gjv5ma7ktfqwsjgn-1
      bzrlib/repofmt/weaverepo.py    presplitout.py-20070125045333-wfav3tsh73oxu3zk-1
      bzrlib/repository.py           rev_storage.py-20051111201905-119e9401e46257e3
      bzrlib/revisionspec.py         revisionspec.py-20050907152633-17567659fd5c0ddb
      bzrlib/smart/branch.py         branch.py-20061124031907-mzh3pla28r83r97f-1
      bzrlib/smart/medium.py         medium.py-20061103051856-rgu2huy59fkz902q-1
      bzrlib/smart/protocol.py       protocol.py-20061108035435-ot0lstk2590yqhzr-1
      bzrlib/tests/__init__.py       selftest.py-20050531073622-8d0e3c8845c97a64
      bzrlib/tests/blackbox/test_branch.py test_branch.py-20060524161337-noms9gmcwqqrfi8y-1
      bzrlib/tests/blackbox/test_check.py test_check.py-20071024054728-mn44rt3z5hnqcbke-1
      bzrlib/tests/blackbox/test_export.py test_export.py-20051229024010-e6c26658e460fb1c
      bzrlib/tests/blackbox/test_info.py test_info.py-20060215045507-bbdd2d34efab9e0a
      bzrlib/tests/blackbox/test_selftest.py test_selftest.py-20060123024542-01c5f1bbcb596d78
      bzrlib/tests/blackbox/test_status.py teststatus.py-20050712014354-508855eb9f29f7dc
      bzrlib/tests/branch_implementations/test_hooks.py test_hooks.py-20070129154855-blhpwxmvjs07waei-1
      bzrlib/tests/branch_implementations/test_stacking.py test_stacking.py-20080214020755-msjlkb7urobwly0f-1
      bzrlib/tests/bzrdir_implementations/test_bzrdir.py test_bzrdir.py-20060131065642-0ebeca5e30e30866
      bzrlib/tests/repository_implementations/test_repository.py test_repository.py-20060131092128-ad07f494f5c9d26c
      bzrlib/tests/test_branch.py    test_branch.py-20060116013032-97819aa07b8ab3b5
      bzrlib/tests/test_branchbuilder.py test_branchbuilder.p-20070427022007-zlxpqz2lannhk6y8-2
      bzrlib/tests/test_errors.py    test_errors.py-20060210110251-41aba2deddf936a8
      bzrlib/tests/test_fetch.py     testfetch.py-20050825090644-f73e07e7dfb1765a
      bzrlib/tests/test_info.py      test_info.py-20070320150933-m0xxm1g7xi9v6noe-1
      bzrlib/tests/test_memorytree.py test_memorytree.py-20060906023413-4wlkalbdpsxi2r4y-3
      bzrlib/tests/test_merge_directive.py test_merge_directive-20070228184838-ja62280spt1g7f4x-2
      bzrlib/tests/test_remote.py    test_remote.py-20060720103555-yeeg2x51vn0rbtdp-2
      bzrlib/tests/test_repository.py test_repository.py-20060131075918-65c555b881612f4d
      bzrlib/tests/test_revision.py  testrevision.py-20050804210559-46f5e1eb67b01289
      bzrlib/tests/test_selftest.py  test_selftest.py-20051202044319-c110a115d8c0456a
      bzrlib/tests/test_smart.py     test_smart.py-20061122024551-ol0l0o0oofsu9b3t-2
      bzrlib/tests/test_transform.py test_transaction.py-20060105172520-b3ffb3946550e6c4
      bzrlib/tests/test_urlutils.py  test_urlutils.py-20060502192900-46b1f9579987cf9c
      bzrlib/tests/tree_implementations/__init__.py __init__.py-20060717075546-420s7b0bj9hzeowi-2
      bzrlib/tests/workingtree_implementations/test_remove.py test_remove.py-20070413183901-rvnp85rtc0q0sclp-1
      bzrlib/transform.py            transform.py-20060105172343-dd99e54394d91687
      bzrlib/transport/http/__init__.py http_transport.py-20050711212304-506c5fd1059ace96
      bzrlib/tree.py                 tree.py-20050309040759-9d5f2496be663e77
      bzrlib/urlutils.py             urlutils.py-20060502195429-e8a161ecf8fac004
      bzrlib/workingtree.py          workingtree.py-20050511021032-29b6ec0a681e02e3
      bzrlib/workingtree_4.py        workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
      doc/developers/HACKING.txt     HACKING-20050805200004-2a5dc975d870f78c
      doc/developers/index.txt       index.txt-20070508041241-qznziunkg0nffhiw-1
      doc/developers/releasing.txt   releasing.txt-20080502015919-fnrcav8fwy8ccibu-1
      tools/doc_generate/autodoc_rstx.py autodoc_rstx.py-20060420024836-3e0d4a526452193c
    ------------------------------------------------------------
    revno: 3565.5.2
    revision-id: mhammond at skippinet.com.au-20080722105302-027b8v2xx2ts1iai
    parent: mhammond at skippinet.com.au-20080722090655-k7uicuhkin9wgf1u
    committer: Mark Hammond <mhammond at skippinet.com.au>
    branch nick: bzr.work.win32binary.tbzr-setup
    timestamp: Tue 2008-07-22 20:53:02 +1000
    message:
      merge inno script changes
    modified:
      tools/win32/bzr.iss.cog        bzr.iss.cog-20060622100836-b3yup582rt3y0nvm-5
    ------------------------------------------------------------
    revno: 3565.5.1
    revision-id: mhammond at skippinet.com.au-20080722090655-k7uicuhkin9wgf1u
    parent: pqm at pqm.ubuntu.com-20080718100017-segv2csk7ux2xs9p
    committer: Mark Hammond <mhammond at skippinet.com.au>
    branch nick: bzr.work.win32binary.tbzr-setup
    timestamp: Tue 2008-07-22 19:06:55 +1000
    message:
      merge setup.py changes for tbzr
    modified:
      setup.py                       setup.py-20050314065409-02f8a0a6e3f9bc70
=== modified file 'setup.py'
--- a/setup.py	2008-07-17 21:28:49 +0000
+++ b/setup.py	2008-08-14 01:41:30 +0000
@@ -95,6 +95,7 @@
 
 from distutils.core import setup
 from distutils.command.install_scripts import install_scripts
+from distutils.command.install_data import install_data
 from distutils.command.build import build
 
 ###############################
@@ -242,6 +243,100 @@
     print
 
 
+def get_tbzr_py2exe_info(includes, excludes, packages, console_targets,
+                         gui_targets):
+    packages.append('tbzrcommands')
+
+    # ModuleFinder can't handle runtime changes to __path__, but
+    # win32com uses them.  Hook this in so win32com.shell is found.
+    import modulefinder
+    import win32com
+    for p in win32com.__path__[1:]:
+        modulefinder.AddPackagePath("win32com", p)
+    for extra in ["win32com.shell"]:
+        __import__(extra)
+        m = sys.modules[extra]
+        for p in m.__path__[1:]:
+            modulefinder.AddPackagePath(extra, p)
+
+    # TBZR points to the TBZR directory
+    tbzr_root = os.environ["TBZR"]
+
+    # Ensure tbzrlib itself is on sys.path
+    sys.path.append(tbzr_root)
+
+    # Ensure our COM "entry-point" is on sys.path
+    sys.path.append(os.path.join(tbzr_root, "shellext", "python"))
+
+    packages.append("tbzrlib")
+    excludes.extend("""pywin pywin.dialogs pywin.dialogs.list
+                       win32ui crawler.Crawler""".split())
+
+    tbzr = dict(
+        modules=["tbzr"],
+        create_exe = False, # we only want a .dll
+    )
+    com_targets.append(tbzr)
+
+    # tbzrcache executables - a "console" version for debugging and a
+    # GUI version that is generally used.
+    tbzrcache = dict(
+        script = os.path.join(tbzr_root, "Scripts", "tbzrcache.py"),
+        icon_resources = [(0,'bzr.ico')],
+    )
+    console_targets.append(tbzrcache)
+
+    # Make a windows version which is the same except for the base name.
+    tbzrcachew = tbzrcache.copy()
+    tbzrcachew["dest_base"]="tbzrcachew"
+    gui_targets.append(tbzrcachew)
+
+    # ditto for the tbzrcommand tool
+    tbzrcommand = dict(
+        script = os.path.join(tbzr_root, "Scripts", "tbzrcommand.py"),
+        icon_resources = [(0,'bzr.ico')],
+    )
+    console_targets.append(tbzrcommand)
+    tbzrcommandw = tbzrcommand.copy()
+    tbzrcommandw["dest_base"]="tbzrcommandw"
+    gui_targets.append(tbzrcommandw)
+    
+    # tbzr tests
+    tbzrtest = dict(
+        script = os.path.join(tbzr_root, "Scripts", "tbzrtest.py"),
+    )
+    console_targets.append(tbzrtest)
+
+    # A utility to see python output from the shell extension - this will
+    # die when we get a c++ extension
+    # any .py file from pywin32's win32 lib will do (other than
+    # win32traceutil itself that is)
+    import winerror
+    win32_lib_dir = os.path.dirname(winerror.__file__)
+    tracer = dict(script = os.path.join(win32_lib_dir, "win32traceutil.py"),
+                  dest_base="tbzr_tracer")
+    console_targets.append(tracer)
+
+
+def get_qbzr_py2exe_info(includes, excludes, packages):
+    # PyQt4 itself still escapes the plugin detection code for some reason...
+    packages.append('PyQt4')
+    excludes.append('PyQt4.elementtree.ElementTree')
+    includes.append('sip') # extension module required for Qt.
+    packages.append('pygments') # colorizer for qbzr
+    # but we can avoid many Qt4 Dlls.
+    dll_excludes.extend(
+        """QtAssistantClient4.dll QtCLucene4.dll QtDesigner4.dll
+        QtHelp4.dll QtNetwork4.dll QtOpenGL4.dll QtScript4.dll
+        QtSql4.dll QtTest4.dll QtWebKit4.dll QtXml4.dll
+        qscintilla2.dll""".split())
+    # the qt binaries might not be on PATH...
+    qt_dir = os.path.join(sys.prefix, "PyQt4", "bin")
+    path = os.environ.get("PATH","")
+    if qt_dir.lower() not in [p.lower() for p in path.split(os.pathsep)]:
+        os.environ["PATH"] = path + os.pathsep + qt_dir
+
+
 if 'bdist_wininst' in sys.argv:
     def find_docs():
         docs = []
@@ -292,6 +387,30 @@
         version_number.append(str(i))
     version_str = '.'.join(version_number)
 
+    # An override to install_data used only by py2exe builds, which arranges
+    # to byte-compile any .py files in data_files (eg, our plugins)
+    # Necessary as we can't rely on the user having the relevant permissions
+    # to the "Program Files" directory to generate them on the fly.
+    class install_data_with_bytecompile(install_data):
+        def run(self):
+            from distutils.util import byte_compile
+
+            install_data.run(self)
+
+            py2exe = self.distribution.get_command_obj('py2exe', False)
+            optimize = py2exe.optimize
+            compile_names = [f for f in self.outfiles if f.endswith('.py')]
+            byte_compile(compile_names,
+                         optimize=optimize,
+                         force=self.force, prefix=self.install_dir,
+                         dry_run=self.dry_run)
+            if optimize:
+                suffix = 'o'
+            else:
+                suffix = 'c'
+            self.outfiles.extend([f + suffix for f in compile_names])
+    # end of class install_data_with_bytecompile
+
     target = py2exe.build_exe.Target(script = "bzr",
                                      dest_base = "bzr",
                                      icon_resources = [(0,'bzr.ico')],
@@ -324,9 +443,29 @@
         import warnings
         warnings.warn('Unknown Python version.\n'
                       'Please check setup.py script for compatibility.')
+
+    # Although we currently can't enforce it, we consider it an error for
+    # py2exe to report any files are "missing".  Such modules we know aren't
+    # used should be listed here.
+    excludes = """Tkinter psyco ElementPath r_hmac
+                  ImaginaryModule cElementTree elementtree.ElementTree
+                  Crypto.PublicKey._fastmath
+                  medusa medusa.filesys medusa.ftp_server
+                  tools tools.doc_generate
+                  resource validate""".split()
+    dll_excludes = []
+
     # email package from std python library use lazy import,
     # so we need to explicitly add all package
     additional_packages.add('email')
+    # And it uses funky mappings to conver to 'Oldname' to 'newname'.  As
+    # a result, packages like 'email.Parser' show as missing.  Tell py2exe
+    # to exclude them.
+    import email
+    for oldname in getattr(email, '_LOWERNAMES', []):
+        excludes.append("email." + oldname)
+    for oldname in getattr(email, '_MIMENAMES', []):
+        excludes.append("email.MIME" + oldname)
 
     # text files for help topis
     text_topics = glob.glob('bzrlib/help_topics/en/*.txt')
@@ -334,10 +473,16 @@
 
     # built-in plugins
     plugins_files = []
+    # XXX - should we consider having the concept of an 'official' build,
+    # which hard-codes the list of plugins, gets more upset if modules are
+    # missing, etc?
+    plugins = None # will be a set after plugin sniffing...
     for root, dirs, files in os.walk('bzrlib/plugins'):
+        if root == 'bzrlib/plugins':
+            plugins = set(dirs)
         x = []
         for i in files:
-            if not i.endswith('.py'):
+            if os.path.splitext(i)[1] not in [".py", ".pyd", ".dll"]:
                 continue
             if i == '__init__.py' and root == 'bzrlib/plugins':
                 continue
@@ -351,22 +496,55 @@
     mf.run_package('bzrlib/plugins')
     packs, mods = mf.get_result()
     additional_packages.update(packs)
+    includes.extend(mods)
+
+    console_targets = [target,
+                       'tools/win32/bzr_postinstall.py',
+                       ]
+    gui_targets = []
+    com_targets = []
+
+    if 'qbzr' in plugins:
+        get_qbzr_py2exe_info(includes, excludes, packages)
+
+    if "TBZR" in os.environ:
+        # TORTOISE_OVERLAYS_MSI_WIN32 must be set to the location of the
+        # TortoiseOverlays MSI installer file. It is in the TSVN svn repo and
+        # can be downloaded from (username=guest, blank password):
+        # http://tortoisesvn.tigris.org/svn/tortoisesvn/TortoiseOverlays/version-1.0.4/bin/TortoiseOverlays-1.0.4.11886-win32.msi
+        if not os.path.isfile(os.environ.get('TORTOISE_OVERLAYS_MSI_WIN32',
+                                             '<nofile>')):
+            raise RuntimeError("Please set TORTOISE_OVERLAYS_MSI_WIN32 to the"
+                               " location of the Win32 TortoiseOverlays .msi"
+                               " installer file")
+        get_tbzr_py2exe_info(includes, excludes, packages, console_targets,
+                             gui_targets)
+    else:
+        # print this warning to stderr as output is redirected, so it is seen
+        # at build time.  Also to stdout so it appears in the log
+        for f in (sys.stderr, sys.stdout):
+            print >> f, \
+                "Skipping TBZR binaries - please set TBZR to a directory to enable"
 
     # MSWSOCK.dll is a system-specific library, which py2exe accidentally pulls
     # in on Vista.
+    dll_excludes.append("MSWSOCK.dll")
     options_list = {"py2exe": {"packages": packages + list(additional_packages),
-                               "includes": includes + mods,
-                               "excludes": ["Tkinter", "medusa", "tools"],
-                               "dll_excludes": ["MSWSOCK.dll"],
+                               "includes": includes,
+                               "excludes": excludes,
+                               "dll_excludes": dll_excludes,
                                "dist_dir": "win32_bzr.exe",
+                               "optimize": 1,
                               },
                    }
+
     setup(options=options_list,
-          console=[target,
-                   'tools/win32/bzr_postinstall.py',
-                  ],
+          console=console_targets,
+          windows=gui_targets,
+          com_server=com_targets,
           zipfile='lib/library.zip',
           data_files=topics_files + plugins_files,
+          cmdclass={'install_data': install_data_with_bytecompile},
           )
 
 else:

=== modified file 'tools/win32/bzr.iss.cog'
--- a/tools/win32/bzr.iss.cog	2008-02-06 15:33:12 +0000
+++ b/tools/win32/bzr.iss.cog	2008-08-14 01:41:30 +0000
@@ -45,8 +45,8 @@
 InfoAfterFile="..\tools\win32\survey.txt"
 
 VersionInfoCompany="Canonical Ltd."
-VersionInfoCopyright="Canonical Ltd., 2005-2007"
-VersionInfoDescription="Installer for stand-alone bzr.exe"
+VersionInfoCopyright="Canonical Ltd., 2005-2008"
+VersionInfoDescription="Windows installer for Bazaar"
 ; [[[cog
 ; import bzrlib
 ; version_number = []
@@ -79,14 +79,43 @@
 ; [[[end]]]
 
 ChangesEnvironment=yes
-PrivilegesRequired=none
-
+; MARKH: PrivilegesRequired=none means it can't be installed by a non-admin
+; user - but sadly we still need admin - eg, tortoise overlays, installing
+; into "\Program Files", installing COM objects etc all must be done by an
+; admin.
+PrivilegesRequired=admin
 
 [Files]
-Source: "*.*"; DestDir: "{app}"; Flags: ignoreversion;
-Source: "lib\*.*"; DestDir: "{app}\lib"; Flags: createallsubdirs ignoreversion recursesubdirs;
-Source: "doc\*.*"; DestDir: "{app}\doc"; Flags: createallsubdirs ignoreversion recursesubdirs;
-Source: "plugins\*.*"; DestDir: "{app}\plugins"; Components: plugins; Flags: createallsubdirs ignoreversion recursesubdirs;
+; Tortoise files - these are at the top as we use 'ExtractTemporaryFile' on
+; the TortoiseOverlays MSI, and inno documents such files should be at the
+; start for best performance.
+; [[[cog
+; if "TBZR" in os.environ: # we need a more formal way of controlling this...
+;     tovmsi = os.environ["TORTOISE_OVERLAYS_MSI_WIN32"] # point at TortoiseOverlays .msi
+;     cog.outl('Source: "%s"; Flags: dontcopy ignoreversion ; Components: tortoise' % tovmsi)
+;     cog.outl('Source: "tbzrcache.exe"; DestDir: "{app}"; Flags: ignoreversion restartreplace uninsrestartdelete; Components: tortoise')
+;     cog.outl('Source: "tbzrcachew.exe"; DestDir: "{app}"; Flags: ignoreversion restartreplace uninsrestartdelete; Components: tortoise')
+;     cog.outl('Source: "tbzrcommand.exe"; DestDir: "{app}"; Flags: ignoreversion restartreplace uninsrestartdelete; Components: tortoise')
+;     cog.outl('Source: "tbzrcommandw.exe"; DestDir: "{app}"; Flags: ignoreversion restartreplace uninsrestartdelete; Components: tortoise')
+;     cog.outl('Source: "tbzr_tracer.exe"; DestDir: "{app}"; Flags: ignoreversion restartreplace uninsrestartdelete; Components: debug')
+;     # Note 'regserver' here appears to run regsvr32 without elevation, which
+;     # is no good for us - so we have a [run] entry below.
+;     cog.outl('Source: "tbzr.dll"; DestDir: "{app}"; Flags: ignoreversion regserver restartreplace uninsrestartdelete; Components: tortoise')
+;     cog.outl(r'Source: "plugins\qbzr\*"; DestDir: "{app}\plugins\qbzr"; Flags: createallsubdirs ignoreversion recursesubdirs restartreplace uninsrestartdelete; Components: tortoise')
+;
+;     cog.outl('Source: "%s\\doc\\index.html"; DestDir: "{app}\\doc\\tbzr"; Flags: ignoreversion; Components: tortoise' % os.environ['TBZR'])
+; ]]]
+; [[[end]]]
+
+; We can't say '*.*' due to optional components.
+Source: "plugins\*.*"; DestDir: "{app}\\plugins"; Flags: createallsubdirs ignoreversion recursesubdirs restartreplace uninsrestartdelete; Components: plugins
+Source: "*.bat"; DestDir: "{app}"; Flags: ignoreversion restartreplace uninsrestartdelete;
+Source: "*.url"; DestDir: "{app}"; Flags: ignoreversion restartreplace uninsrestartdelete;
+Source: "msvc*.dll"; DestDir: "{app}"; Flags: ignoreversion restartreplace uninsrestartdelete;
+Source: "bz*.exe"; DestDir: "{app}"; Flags: ignoreversion restartreplace uninsrestartdelete;
+Source: "Python*.dll"; DestDir: "{app}"; Flags: ignoreversion restartreplace uninsrestartdelete;
+Source: "lib\*.*"; DestDir: "{app}\lib"; Flags: createallsubdirs ignoreversion recursesubdirs restartreplace uninsrestartdelete;
+Source: "doc\*.*"; DestDir: "{app}\doc"; Flags: createallsubdirs ignoreversion recursesubdirs restartreplace uninsrestartdelete;
 ; [[[cog
 ; try:
 ;     import pycurl
@@ -105,19 +134,27 @@
 ; ]]]
 ; [[[end]]]
 
+[Types]
+Name: "typical"; Description: "A typical installation"
+Name: "full"; Description: "Full Installation (typical installation plus test utilities)"
+Name: "compact"; Description: "Compact installation"
+Name: "custom"; Description: "Custom installation"; Flags: iscustom
 
 [Components]
-Name: "main"; Description: "Main Files"; Types: full compact custom; Flags: fixed
-Name: "plugins"; Description: "Default plugins"; Types: full custom;
+Name: "main"; Description: "Main Files"; Types: full typical compact custom; Flags: fixed
+Name: "plugins"; Description: "Default plugins"; Types: full typical custom;
 ; [[[cog
 ; if ca_path:
 ;     cog.outl('Name: "cabundle"; '
 ;              'Description: "CA certificates for SSL support"; '
-;              'Types: full custom')
+;              'Types: full typical custom')
+; if "TBZR" in os.environ: # we need a more formal way of controlling this...
+;     cog.outl('Name: "tortoise"; Description: "Windows Shell Extensions (TortoiseBZR) - EXPERIMENTAL"; Types: full typical custom;')
+;     cog.outl('Name: "debug"; Description: "Test, diagnostic and debugging utilities"; Types: full custom;')
+;
 ; ]]]
 ; [[[end]]]
 
-
 [Dirs]
 Name: "{userappdata}\bazaar\2.0"
 Name: "{app}\plugins"; Flags: uninsalwaysuninstall
@@ -127,41 +164,121 @@
 Name: "{group}\Documentation index"; Filename: "{app}\doc\index.html"; WorkingDir: "{app}\doc";
 Name: "{group}\Bazaar Home Page"; Filename: "{app}\bazaar.url"; Comment: "http://www.bazaar-vcs.org";
 Name: "{group}\Start Bzr in cmd shell"; Filename: "{cmd}"; Parameters: "/K start_bzr.bat"; WorkingDir: "{app}"; IconFilename: "{app}\bzr.exe"; Comment: "Open new Bzr session";
-Name: "{group}\Uninstall Bazaar"; Filename: "{uninstallexe}"; IconFileName: "{sys}\shell32.dll"; IconIndex: 101; Comment: "Remove Bzr completely";
+; NOTE: Intent is to change the log file location - the line below will need to change to reflect that.
+Name: "{group}\Open Bzr log file"; Filename: "notepad.exe"; Parameters: "{userdocs}\.bzr.log"; Comment: "Launch notepad to view the bzr log file";
+
+; [[[cog
+; if "TBZR" in os.environ:
+;     cog.outl(r'Name: "{group}\TortoiseBZR documentation"; Filename: "{app}\doc\tbzr\index.html"; Comment: "Launch TortoiseBZR documentation";')
+; ]]]
+; [[[end]]]
+; No Uninstall here - Control Panel will do
 
 
 [Tasks]
-Name: Path; Description: "Add {app} directory to PATH environment variable";
+Name: Path; Description: "Add {app} directory to PATH environment variable"
 Name: Shell; Description: "Add Bzr context menu to shell"; Flags: unchecked
+; [[[cog
+; if "TBZR" in os.environ:
+;     cog.outl('Name: TBZRReadme; Description: "View the TortoiseBZR Readme"; Components: tortoise')
+; ]]]
+; [[[end]]]
 
 
 [Registry]
 Root: HKLM; Subkey: "SOFTWARE\Bazaar"; Flags: noerror uninsdeletekey
 Root: HKLM; Subkey: "SOFTWARE\Bazaar"; ValueName: "InstallPath"; ValueType: string; ValueData: "{app}"; Flags: noerror
-Root: HKLM; Subkey: "SOFTWARE\Bazaar"; ValueName: "BzrlibPath"; ValueType: string; ValueData: "{app}\lib\library.zip\bzrlib"; Flags: noerror
-Root: HKLM; Subkey: "SOFTWARE\Bazaar"; ValueName: "PluginsPath"; ValueType: string; ValueData: "{app}\plugins"; Flags: noerror
-Root: HKLM; Subkey: "SOFTWARE\Bazaar"; ValueName: "PythonPath"; ValueType: string; ValueData: "{app}\lib\library.zip"; Flags: noerror
+; Don't write stuff that can be implied
+;Root: HKLM; Subkey: "SOFTWARE\Bazaar"; ValueName: "BzrlibPath"; ValueType: string; ValueData: "{app}\lib\library.zip\bzrlib"; Flags: noerror
+;Root: HKLM; Subkey: "SOFTWARE\Bazaar"; ValueName: "PluginsPath"; ValueType: string; ValueData: "{app}\plugins"; Flags: noerror
+;Root: HKLM; Subkey: "SOFTWARE\Bazaar"; ValueName: "PythonPath"; ValueType: string; ValueData: "{app}\lib\library.zip"; Flags: noerror
 ; [[[cog cog.outl('Root: HKLM; Subkey: "SOFTWARE\Bazaar"; ValueName: "Version"; ValueType: string; ValueData: "%s"; Flags: noerror' % VERSION) ]]]
 ; [[[end]]]
 
 
 [Run]
 Filename: "{app}\bzr_postinstall.exe"; Parameters: "--start-bzr"; Flags: skipifdoesntexist runhidden;
-; [[[cog
-; import os
-; if os.path.isfile('win32_bzr.exe/lib/win32ui.pyd'):	# pywin32 mfc wrapper
-;     cog.outl('Filename: "{app}\bzr_postinstall.exe"; '
-;              'Parameters: "--check-mfc71"; '
-;              'Flags: skipifdoesntexist skipifsilent runhidden;')
-; ]]]
-; [[[end]]]
 Filename: "{app}\bzr_postinstall.exe"; Parameters: "--add-path"; Tasks: Path; Flags: skipifdoesntexist skipifsilent runhidden;
 Filename: "{app}\bzr_postinstall.exe"; Parameters: "--add-shell-menu"; Tasks: Shell; Flags: skipifdoesntexist skipifsilent runhidden;
+; [[[cog
+; if "TBZR" in os.environ:
+;     cog.outl('Filename: "regsvr32.exe"; Parameters: "/s tbzr.dll"; WorkingDir: "{app}"; Components: tortoise; Description: "Registering Tortoise"; StatusMsg: "Registering Tortoise"')
+;     cog.outl(r'Filename: "{app}\doc\tbzr\index.html"; Tasks: TBZRReadme; Flags: shellexec')
+; ]]]
+; [[[end]]]
 
 
 [UninstallRun]
-Filename: "{app}\bzr_postinstall.exe"; Parameters: "--delete-path --delete-shell-menu --silent"; Flags: skipifdoesntexist runhidden; 
-
-
-[UninstallDelete]
-Type: filesandordirs; Name: "{app}\plugins\*"
+; [[[cog
+; if "TBZR" in os.environ:
+;     cog.outl('Filename: "regsvr32.exe"; Parameters: "/u /s tbzr.dll"; WorkingDir: "{app}"; Components: tortoise; StatusMsg: "Unregistering Tortoise"; Flags: skipifdoesntexist')
+; ]]]
+; [[[end]]]
+
+[Code]
+const
+  SHCNF_IDLIST = $0000;
+  SHCNE_ASSOCCHANGED = $08000000;
+  WM_QUIT = 18;
+
+procedure SHChangeNotify(wEventId, uFlags, dwItem1, dwItem2: Integer);
+ external 'SHChangeNotify at shell32.dll stdcall';
+
+procedure ShutdownTBZR;
+var
+    hwnd: HWND;
+begin
+// [[[cog
+// if "TBZR" not in os.environ:
+//     cog.outl('        Exit;  // No TSVN set - exit this procedure.')
+// ]]]
+// [[[end]]]
+    // ask the cache process to shut-down.
+    hwnd := FindWindowByClassName('TBZRCache_Taskbar');
+    if hwnd <> 0 then
+        PostMessage(hwnd, WM_QUIT, 1, 0);
+end;
+
+procedure CurStepChanged(CurStep: TSetupStep);
+var
+    S, tovmsi, fqtovmsi, params: String;
+    ErrorCode: Integer;
+begin
+    if CurStep=ssInstall then begin
+        ShutdownTBZR;
+    end;
+
+    if CurStep=ssPostInstall then begin
+        // a couple of post-install tasks
+        if IsComponentSelected('tortoise') then begin
+            // Need to execute:
+            // msiexec /i TortoiseOverlays-1.X.X.XXXX-win32.msi /qn /norestart
+// [[[cog
+// if "TBZR" in os.environ:
+//     import os
+//     cog.outl("tovmsi := '%s';" % os.path.basename(os.environ["TORTOISE_OVERLAYS_MSI_WIN32"]))
+// else:
+//     cog.outl("tovmsi := '';")
+// ]]]
+// [[[end]]]
+            ExtractTemporaryFile(tovmsi);
+            fqtovmsi := AddBackslash(ExpandConstant('{tmp}')) + tovmsi;
+            params := '/i "' + fqtovmsi + '" /qn /norestart';
+            if not ShellExec('', 'msiexec.exe', params, '', SW_HIDE,
+                             ewWaitUntilTerminated, ErrorCode) then
+                MsgBox('Failed to install TortoiseOverlays: ' + SysErrorMessage(ErrorCode),
+                        mbInformation, MB_OK);
+            // Ideally we could be bzr_postinstall.exe this way too, but
+            // its needed at uninstall time.
+        end;
+        // cause explorer to re-fetch handlers.
+        SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0);
+    end;
+end;
+
+
+function InitializeUninstall(): Boolean; 
+begin
+    ShutdownTBZR;
+    result := True;
+end;




More information about the bazaar-commits mailing list