Example #1
0
def create(info, verbose=False):
    verify_nsis_install()
    tmp_dir = tempfile.mkdtemp()
    preconda.write_files(info, tmp_dir)
    if 'pre_install' in info:
        sys.exit("Error: Cannot run pre install on Windows, sorry.\n")

    post_dst = join(tmp_dir, 'post_install.bat')
    try:
        shutil.copy(info['post_install'], post_dst)
    except KeyError:
        with open(post_dst, 'w') as fo:
            fo.write(":: this is an empty post install .bat script\n")

    write_images(info, tmp_dir)
    nsi = make_nsi(info, tmp_dir)
    if verbose:
        verbosity = '/V4'
    else:
        verbosity = '/V2'
    args = [MAKENSIS_EXE, verbosity, nsi]
    print('Calling: %s' % args)
    if verbose:
        sub = Popen(args, stdout=PIPE, stderr=PIPE)
        stdout, stderr = sub.communicate()
        for msg, info in zip((stdout, stderr), ('stdout', 'stderr')):
            # on Python3 we're getting bytes
            if hasattr(msg, 'decode'):
                msg = msg.decode()
            print('makensis {}:'.format(info))
            print(msg)
    else:
        check_call(args)
    shutil.rmtree(tmp_dir)
Example #2
0
def test_write_images():
    tmp_dir = tempfile.mkdtemp()

    info = {'name': 'test', 'version': '0.3.1'}
    write_images(info, tmp_dir)

    shutil.rmtree(tmp_dir)
Example #3
0
def create(info):
    verify_nsis_install()
    tmp_dir = tempfile.mkdtemp()
    write_images(info, tmp_dir)
    nsi = make_nsi(info, tmp_dir)
    args = [MAKENSIS_EXE, '/V2', nsi]
    print('Calling: %s' % args)
    check_call(args)
    shutil.rmtree(tmp_dir)
Example #4
0
def create(info):
    verify_nsis_install()
    tmp_dir = tempfile.mkdtemp()
    write_images(info, tmp_dir)
    nsi = make_nsi(info, tmp_dir)
    args = [MAKENSIS_EXE, '/V2', nsi]
    print('Calling: %s' % args)
    check_call(args)
    shutil.rmtree(tmp_dir)
Example #5
0
def test_write_images():
    tmp_dir = tempfile.mkdtemp()

    info = {'name': 'test', 'version': '0.3.1'}
    for key in ('welcome_image_text', 'header_image_text'):
        if key not in info:
            info[key] = info['name']

    write_images(info, tmp_dir)

    shutil.rmtree(tmp_dir)
Example #6
0
def create(info):
    verify_nsis_install()
    tmp_dir = tempfile.mkdtemp()
    preconda.write_files(info, tmp_dir)
    if 'pre_install' in info:
        sys.exit("Error: Cannot run pre install on Windows, sorry.\n")

    post_dst = join(tmp_dir, 'post_install.bat')
    try:
        shutil.copy(info['post_install'], post_dst)
    except KeyError:
        with open(post_dst, 'w') as fo:
            fo.write(":: this is an empty post install .bat script\n")

    write_images(info, tmp_dir)
    nsi = make_nsi(info, tmp_dir)
    args = [MAKENSIS_EXE, '/V2', nsi]
    print('Calling: %s' % args)
    check_call(args)
    shutil.rmtree(tmp_dir)
Example #7
0
def create(info):
    verify_nsis_install()
    tmp_dir = tempfile.mkdtemp()
    preconda.write_files(info, tmp_dir)
    if 'pre_install' in info:
        sys.exit("Error: Cannot run pre install on Windows, sorry.\n")

    post_dst = join(tmp_dir, 'post_install.bat')
    try:
        shutil.copy(info['post_install'], post_dst)
    except KeyError:
        with open(post_dst, 'w') as fo:
            fo.write(":: this is an empty post install .bat script\n")

    write_images(info, tmp_dir)
    nsi = make_nsi(info, tmp_dir)
    args = [MAKENSIS_EXE, '/V2', nsi]
    print('Calling: %s' % args)
    check_call(args)
    shutil.rmtree(tmp_dir)
Example #8
0
def modify_xml(xml_path, info):
    # See
    # http://developer.apple.com/library/mac/#documentation/DeveloperTools/Reference/DistributionDefinitionRef/Chapters/Distribution_XML_Ref.html#//apple_ref/doc/uid/TP40005370-CH100-SW20
    # for all the options you can put here.

    tree = ET.parse(xml_path)
    root = tree.getroot()

    title = ET.Element('title')
    title.text = f"{info['name']} {info['version']}"
    root.append(title)

    license = ET.Element('license', file=info.get('license_file',
                                                  'No license'))
    root.append(license)

    ### BACKGROUND ###
    # Default setting for the background was using Anaconda's logo
    # located at ./osx/MacInstaller.png. If `welcome_image` or
    # `welcome_image_text` are not provided, this will still happen.
    # However, if the user provides one of those, we will use that instead.
    # If no background is desired, set `welcome_image` to None
    if "welcome_image" in info:
        if not info["welcome_image"]:
            background_path = None
        else:
            write_images(info, PACKAGES_DIR, os="osx")
            background_path = os.path.join(PACKAGES_DIR, "welcome.png")
    elif "welcome_image_text" in info:
        write_images(info, PACKAGES_DIR, os="osx")
        background_path = os.path.join(PACKAGES_DIR, "welcome.png")
    else:
        # Default to Anaconda's logo if the keys above were not specified
        background_path = join(OSX_DIR, 'MacInstaller.png')

    if background_path:
        print("Using background image", background_path)
        for key in ("background", "background-darkAqua"):
            background = ET.Element(key,
                                    file=background_path,
                                    scaling='proportional',
                                    alignment='center')
            root.append(background)

    ### WELCOME ###
    if "welcome_file" in info:
        welcome_path = info["welcome_file"]
    elif "welcome_text" in info and info["welcome_text"]:
        welcome_path = join(PACKAGES_DIR, "welcome.txt")
        with open(welcome_path, "w") as f:
            f.write(info["welcome_text"])
    else:
        welcome_path = None

    if welcome_path:
        welcome = ET.Element(
            'welcome', file=welcome_path,
            attrib={'mime-type': _detect_mimetype(welcome_path)}
        )
        root.append(welcome)

    ### CONCLUSION ###
    if "conclusion_file" in info:
        conclusion_path = info["conclusion_file"]
    elif "conclusion_text" in info:
        if not info["conclusion_text"]:
            conclusion_path = None
        else:
            conclusion_path = join(PACKAGES_DIR, "conclusion.txt")
            with open(conclusion_path, "w") as f:
                f.write(info["conclusion_text"])
    else:
        conclusion_path = join(OSX_DIR, 'acloud.rtf')

    if conclusion_path:
        conclusion = ET.Element(
            'conclusion', file=conclusion_path,
            attrib={'mime-type': _detect_mimetype(conclusion_path)}
        )
        root.append(conclusion)
    # when not provided, conclusion defaults to a system message

    ### README ###
    if "readme_file" in info:
        readme_path = info["readme_file"]
    elif "readme_text" in info:
        if not info["readme_text"]:
            readme_path = None
        else:
            readme_path = join(PACKAGES_DIR, "readme.txt")
            with open(readme_path, "w") as f:
                f.write(info["readme_text"])
    else:
        readme_path = join(PACKAGES_DIR, "readme.rtf")
        write_readme(readme_path, info)

    if readme_path:
        readme = ET.Element(
            'readme', file=readme_path,
            attrib={'mime-type': _detect_mimetype(readme_path)}
        )
        root.append(readme)

    # See below for an explanation of the consequences of this
    # customLocation value.
    for options in root.findall('options'):
        options.set('customize', 'allow')
        options.set('customLocation', '/')

    # By default, the package builder puts all of our options under
    # a single master choice. This deletes that master choice and
    # allows the user to see all options without effort.
    for choices_outline in root.findall('choices-outline'):
        [child] = list(choices_outline)
        choices_outline.extend(list(child))
        choices_outline.remove(child)

    for path_choice in root.findall('choice'):
        ident = path_choice.get('id')
        if ident == 'default':
            root.remove(path_choice)
        elif ident.endswith('main'):
            path_choice.set('visible', 'true')
            path_choice.set('title', 'Install {}'.format(info['name']))
            path_choice.set('enabled', 'false')
        elif ident.endswith('postinstall') and info.get('post_install_desc'):
            path_choice.set('visible', 'true')
            path_choice.set('title', "Run the post-install script")
            path_choice.set('description', ' '.join(info['post_install_desc'].split()))
        elif ident.endswith('pathupdate'):
            has_conda = info.get('_has_conda', True)
            path_choice.set('visible', 'true' if has_conda else 'false')
            path_choice.set('start_selected', 'true' if has_conda and info.get(
                'initialize_by_default', True) else 'false')
            path_choice.set('title', "Add conda initialization to the shell")
            path_description = """
            If this box is checked, "conda init" will be executed to ensure that
            conda is available in your preferred shell upon startup. If unchecked,
            you must this initialization yourself or activate the environment
            manually for each shell in which you wish to use it."""
            path_choice.set('description', ' '.join(path_description.split()))
        elif ident.endswith('cacheclean'):
            path_choice.set('visible', 'true')
            path_choice.set('title', "Clear the package cache")
            path_choice.set('start_selected', 'false' if info.get('keep_pkgs') else 'true')
            cache_size_mb = approx_size_kb(info, "tarballs") // 1024
            size_text = f"~{cache_size_mb}MB" if cache_size_mb > 0 else "some space"
            path_description = f"""
            If this box is checked, the package cache will be cleaned after the
            installer is complete, reclaiming {size_text}. If unchecked, the
            package cache contents will be preserved.
            """
            path_choice.set('description', ' '.join(path_description.split()))

    # The "customLocation" option is set above to "/", which
    # means that the installer defaults to the following locations:
    # - Install for all users: /<name>
    # - Install for this user: /Users/<username>/<name>
    # - Install on a specific disk: /<custom_root>/<name>
    # On modern Mac systems, installing in root is not allowed. So
    # we remove this option by not supplying enable_localSystem
    # below. Alternatively, we could have chosen not to set the
    # value of customLocation and we would have obtained this:
    # - Install for all users: /Applications/<name>
    # - Install for this user: /Users/<username>/Applications/<name>
    # - Install on a specific disk: /<custom_root>/<name>
    # We have chosen not to do this so that this installer
    # produces the same results as a shell install.
    domains = ET.Element('domains',
                         enable_anywhere='true',
                         enable_currentUserHome='true')
    root.append(domains)
    tree.write(xml_path)