def go(self, procs):
        """Writes out config.js, marker.js, and region.js
        Copies web assets into the destdir"""
        zoomlevel = self.p

        bgcolor = (int(self.bg_color[1:3], 16), int(self.bg_color[3:5], 16), int(self.bg_color[5:7], 16), 0)
        blank = Image.new("RGBA", (1, 1), bgcolor)
        # Write a blank image
        for quadtree in self.quadtrees:
            tileDir = os.path.join(self.destdir, quadtree.tiledir)
            if not os.path.exists(tileDir):
                os.mkdir(tileDir)
            blank.save(os.path.join(tileDir, "blank." + quadtree.imgformat))

        # copy web assets into destdir:
        mirror_dir(os.path.join(util.get_program_path(), "web_assets"), self.destdir)
        # do the same with the local copy, if we have it
        if self.web_assets_path:
            mirror_dir(self.web_assets_path, self.destdir)

        # replace the config js stuff
        config = open(os.path.join(self.destdir, "overviewerConfig.js"), "r").read()
        config = config.replace("{minzoom}", str(0))
        config = config.replace("{maxzoom}", str(zoomlevel))

        config = config.replace("{spawn_coords}", json.dumps(list(self.world.spawn)))

        # config = config.replace("{bg_color}", self.bg_color)

        # create generated map type data, from given quadtrees
        maptypedata = map(
            lambda q: {
                "label": q.rendermode.capitalize(),
                "path": q.tiledir,
                "bg_color": self.bg_color,
                "overlay": "overlay" in get_render_mode_inheritance(q.rendermode),
                "imgformat": q.imgformat,
            },
            self.quadtrees,
        )
        config = config.replace("{maptypedata}", json.dumps(maptypedata))

        with open(os.path.join(self.destdir, "overviewerConfig.js"), "w") as output:
            output.write(config)

        # Add time and version in index.html
        indexpath = os.path.join(self.destdir, "index.html")

        index = open(indexpath, "r").read()
        index = index.replace("{time}", str(strftime("%a, %d %b %Y %H:%M:%S %Z", localtime())))
        index = index.replace("{version}", util.findGitVersion())

        with open(os.path.join(self.destdir, "index.html"), "w") as output:
            output.write(index)

        if self.skipjs:
            if self.web_assets_hook:
                self.web_assets_hook(self)
            return
    def output_noconfig(self):

        # copy web assets into destdir:
        global_assets = os.path.join(util.get_program_path(),
                                     "overviewer_core", "data", "web_assets")
        if not os.path.isdir(global_assets):
            global_assets = os.path.join(util.get_program_path(), "web_assets")
        mirror_dir(global_assets, self.outputdir, capabilities=self.fs_caps)

        if self.custom_assets_dir:
            # Could have done something fancy here rather than just overwriting
            # the global files, but apparently this what we used to do pre-rewrite.
            mirror_dir(self.custom_assets_dir,
                       self.outputdir,
                       capabilities=self.fs_caps)

# write a dummy baseMarkers.js if none exists
        if not os.path.exists(os.path.join(self.outputdir, "baseMarkers.js")):
            with open(os.path.join(self.outputdir, "baseMarkers.js"),
                      "w") as f:
                f.write("// if you wants signs, please see genPOI.py\n")

        # create overviewer.js from the source js files
        js_src = os.path.join(util.get_program_path(), "overviewer_core",
                              "data", "js_src")
        if not os.path.isdir(js_src):
            js_src = os.path.join(util.get_program_path(), "js_src")
        with FileReplacer(os.path.join(self.outputdir, "overviewer.js"),
                          capabilities=self.fs_caps) as tmpfile:
            with open(tmpfile, "w") as fout:
                # first copy in js_src/overviewer.js
                with open(os.path.join(js_src, "overviewer.js"), 'r') as f:
                    fout.write(f.read())
                # now copy in the rest
                for js in os.listdir(js_src):
                    if not js.endswith("overviewer.js") and js.endswith(".js"):
                        with open(os.path.join(js_src, js)) as f:
                            fout.write(f.read())

        # Add time and version in index.html
        indexpath = os.path.join(self.outputdir, "index.html")

        index = codecs.open(indexpath, 'r', encoding='UTF-8').read()
        index = index.replace("{title}", "Minecraft Overviewer")
        index = index.replace("{google_api_key}", self.google_api_key)
        index = index.replace(
            "{time}",
            time.strftime("%a, %d %b %Y %H:%M:%S %Z",
                          time.localtime()).decode(self.preferredencoding))
        versionstr = "%s (%s)" % (util.findGitVersion(),
                                  util.findGitHash()[:7])
        index = index.replace("{version}", versionstr)

        with FileReplacer(indexpath, capabilities=self.fs_caps) as indexpath:
            with codecs.open(indexpath, 'w', encoding='UTF-8') as output:
                output.write(index)
 def run(self):
     try:
         import util
         f = open("overviewer_version.py", "w")
         f.write("VERSION=%r\n" % util.findGitVersion())
         f.write("BUILD_DATE=%r\n" % time.asctime())
         f.write("BUILD_PLATFORM=%r\n" % platform.processor())
         f.write("BUILD_OS=%r\n" % platform.platform())
         f.close()
         setup_kwargs['data_files'].append(('.', ['overviewer_version.py']))
     except:
         print "WARNING: failed to build overview_version file"
     py2exe.build_exe.py2exe.run(self)
    def output_noconfig(self):

        # copy web assets into destdir:
        global_assets = os.path.join(util.get_program_path(), "overviewer_core", "data", "web_assets")
        if not os.path.isdir(global_assets):
            global_assets = os.path.join(util.get_program_path(), "web_assets")
        mirror_dir(global_assets, self.outputdir, capabilities=self.fs_caps)

        if self.custom_assets_dir:
            # Could have done something fancy here rather than just overwriting
            # the global files, but apparently this what we used to do pre-rewrite.
            mirror_dir(self.custom_assets_dir, self.outputdir, capabilities=self.fs_caps)

        # write a dummy baseMarkers.js if none exists
        if not os.path.exists(os.path.join(self.outputdir, "baseMarkers.js")):
            with open(os.path.join(self.outputdir, "baseMarkers.js"), "w") as f:
                f.write("// if you wants signs, please see genPOI.py\n")

        # create overviewer.js from the source js files
        js_src = os.path.join(util.get_program_path(), "overviewer_core", "data", "js_src")
        if not os.path.isdir(js_src):
            js_src = os.path.join(util.get_program_path(), "js_src")
        with FileReplacer(os.path.join(self.outputdir, "overviewer.js"), capabilities=self.fs_caps) as tmpfile:
            with open(tmpfile, "w") as fout:
                # first copy in js_src/overviewer.js
                with open(os.path.join(js_src, "overviewer.js"), "r") as f:
                    fout.write(f.read())
                # now copy in the rest
                for js in os.listdir(js_src):
                    if not js.endswith("overviewer.js") and js.endswith(".js"):
                        with open(os.path.join(js_src, js)) as f:
                            fout.write(f.read())

        # Add time and version in index.html
        indexpath = os.path.join(self.outputdir, "index.html")

        index = codecs.open(indexpath, "r", encoding="UTF-8").read()
        index = index.replace("{title}", "Minecraft Overviewer")
        index = index.replace(
            "{time}", time.strftime("%a, %d %b %Y %H:%M:%S %Z", time.localtime()).decode(self.preferredencoding)
        )
        versionstr = "%s (%s)" % (util.findGitVersion(), util.findGitHash()[:7])
        index = index.replace("{version}", versionstr)

        with FileReplacer(indexpath, capabilities=self.fs_caps) as indexpath:
            with codecs.open(indexpath, "w", encoding="UTF-8") as output:
                output.write(index)
def main():
    try:
        cpus = multiprocessing.cpu_count()
    except NotImplementedError:
        cpus = 1

    avail_rendermodes = c_overviewer.get_render_modes()

    parser = ConfigOptionParser(usage=helptext, config="settings.py")
    parser.add_option(
        "-V", "--version", dest="version", help="Displays version information and then exits", action="store_true"
    )
    parser.add_option(
        "-p",
        "--processes",
        dest="procs",
        help="How many worker processes to start. Default %s" % cpus,
        default=cpus,
        action="store",
        type="int",
    )
    parser.add_option(
        "-z",
        "--zoom",
        dest="zoom",
        help="Sets the zoom level manually instead of calculating it. This can be useful if you have outlier chunks that make your world too big. This value will make the highest zoom level contain (2**ZOOM)^2 tiles",
        action="store",
        type="int",
        configFileOnly=True,
    )
    parser.add_option(
        "-d",
        "--delete",
        dest="delete",
        help="Clear all caches. Next time you render your world, it will have to start completely over again. This is probably not a good idea for large worlds. Use this if you change texture packs and want to re-render everything.",
        action="store_true",
        commandLineOnly=True,
    )
    parser.add_option(
        "--chunklist",
        dest="chunklist",
        help="A file containing, on each line, a path to a chunkfile to update. Instead of scanning the world directory for chunks, it will just use this list. Normal caching rules still apply.",
    )
    parser.add_option(
        "--rendermodes",
        dest="rendermode",
        help="Specifies the render types, separated by commas. Use --list-rendermodes to list them all.",
        type="choice",
        choices=avail_rendermodes,
        required=True,
        default=avail_rendermodes[0],
        listify=True,
    )
    parser.add_option(
        "--list-rendermodes",
        dest="list_rendermodes",
        action="store_true",
        help="List available render modes and exit.",
        commandLineOnly=True,
    )
    parser.add_option(
        "--imgformat",
        dest="imgformat",
        help="The image output format to use. Currently supported: png(default), jpg.",
        configFileOnly=True,
    )
    parser.add_option(
        "--imgquality",
        dest="imgquality",
        default=95,
        help='Specify the quality of image output when using imgformat="jpg".',
        type="int",
        configFileOnly=True,
    )
    parser.add_option(
        "--bg_color",
        dest="bg_color",
        help="Configures the background color for the GoogleMap output.  Specify in #RRGGBB format",
        configFileOnly=True,
        type="string",
        default="#1A1A1A",
    )
    parser.add_option(
        "--optimize-img",
        dest="optimizeimg",
        help="If using png, perform image file size optimizations on the output. Specify 1 for pngcrush, 2 for pngcrush+optipng+advdef. This may double (or more) render times, but will produce up to 30% smaller images. NOTE: requires corresponding programs in $PATH or %PATH%",
        configFileOnly=True,
    )
    parser.add_option(
        "--web-assets-hook",
        dest="web_assets_hook",
        help="If provided, run this function after the web assets have been copied, but before actual tile rendering begins. It should accept a QuadtreeGen object as its only argument.",
        action="store",
        metavar="SCRIPT",
        type="function",
        configFileOnly=True,
    )
    parser.add_option(
        "--web-assets-path",
        dest="web_assets_path",
        help="Specifies a non-standard web_assets directory to use. Files here will overwrite the default web assets.",
        metavar="PATH",
        type="string",
        configFileOnly=True,
    )
    parser.add_option(
        "--textures-path",
        dest="textures_path",
        help="Specifies a non-standard textures path, from which terrain.png and other textures are loaded.",
        metavar="PATH",
        type="string",
        configFileOnly=True,
    )
    parser.add_option(
        "-q",
        "--quiet",
        dest="quiet",
        action="count",
        default=0,
        help="Print less output. You can specify this option multiple times.",
    )
    parser.add_option(
        "-v",
        "--verbose",
        dest="verbose",
        action="count",
        default=0,
        help="Print more output. You can specify this option multiple times.",
    )
    parser.add_option("--skip-js", dest="skipjs", action="store_true", help="Don't output marker.js or regions.js")
    parser.add_option(
        "--display-config",
        dest="display_config",
        action="store_true",
        help="Display the configuration parameters, but don't render the map.  Requires all required options to be specified",
        commandLineOnly=True,
    )
    # parser.add_option("--write-config", dest="write_config", action="store_true", help="Writes out a sample config file", commandLineOnly=True)

    options, args = parser.parse_args()

    if options.version:
        print "Minecraft-Overviewer"
        print "Git version: %s" % util.findGitVersion()
        try:
            import overviewer_version

            if hasattr(sys, "frozen"):
                print "py2exe version build on %s" % overviewer_version.BUILD_DATE
                print "Build machine: %s %s" % (overviewer_version.BUILD_PLATFORM, overviewer_version.BUILD_OS)
        except:
            pass
        sys.exit(0)

    if options.list_rendermodes:
        rendermode_info = map(c_overviewer.get_render_mode_info, avail_rendermodes)
        name_width = max(map(lambda i: len(i["name"]), rendermode_info))
        for info in rendermode_info:
            print "{name:{0}} {description}".format(name_width, **info)
        sys.exit(0)

    if len(args) < 1:
        logging.error("You need to give me your world number or directory")
        parser.print_help()
        list_worlds()
        sys.exit(1)
    worlddir = args[0]

    if not os.path.exists(worlddir):
        # world given is either world number, or name
        worlds = world.get_worlds()

        # if there are no worlds found at all, exit now
        if not worlds:
            parser.print_help()
            logging.error("Invalid world path")
            sys.exit(1)

        try:
            worldnum = int(worlddir)
            worlddir = worlds[worldnum]["path"]
        except ValueError:
            # it wasn't a number or path, try using it as a name
            try:
                worlddir = worlds[worlddir]["path"]
            except KeyError:
                # it's not a number, name, or path
                parser.print_help()
                logging.error("Invalid world name or path")
                sys.exit(1)
        except KeyError:
            # it was an invalid number
            parser.print_help()
            logging.error("Invalid world number")
            sys.exit(1)

    if len(args) < 2:
        if options.delete:
            return delete_all(worlddir, None)
        logging.error("Where do you want to save the tiles?")
        sys.exit(1)
    elif len(args) > 2:
        if options.delete:
            return delete_all(worlddir, None)
        parser.print_help()
        logging.error("Sorry, you specified too many arguments")
        sys.exit(1)

    destdir = args[1]
    if options.display_config:
        # just display the config file and exit
        parser.display_config()
        sys.exit(0)

    if options.delete:
        return delete_all(worlddir, destdir)

    if options.chunklist:
        chunklist = open(options.chunklist, "r")
    else:
        chunklist = None

    if options.imgformat:
        if options.imgformat not in ("jpg", "png"):
            parser.error("Unknown imgformat!")
        else:
            imgformat = options.imgformat
    else:
        imgformat = "png"

    if options.optimizeimg:
        optimizeimg = int(options.optimizeimg)
        optimizeimages.check_programs(optimizeimg)
    else:
        optimizeimg = None

    logging.getLogger().setLevel(logging.getLogger().level + 10 * options.quiet)
    logging.getLogger().setLevel(logging.getLogger().level - 10 * options.verbose)

    logging.info("Welcome to Minecraft Overviewer!")
    logging.debug("Current log level: {0}".format(logging.getLogger().level))

    useBiomeData = os.path.exists(os.path.join(worlddir, "biomes"))
    if not useBiomeData:
        logging.info("Notice: Not using biome data for tinting")

    # First do world-level preprocessing
    w = world.World(worlddir, useBiomeData=useBiomeData)
    w.go(options.procs)

    logging.info("Rending the following tilesets: %s", ",".join(options.rendermode))

    bgcolor = (int(options.bg_color[1:3], 16), int(options.bg_color[3:5], 16), int(options.bg_color[5:7], 16), 0)

    # create the quadtrees
    # TODO chunklist
    q = []
    qtree_args = {
        "depth": options.zoom,
        "imgformat": imgformat,
        "imgquality": options.imgquality,
        "optimizeimg": optimizeimg,
        "bgcolor": bgcolor,
    }
    for rendermode in options.rendermode:
        if rendermode == "normal":
            qtree = quadtree.QuadtreeGen(w, destdir, rendermode=rendermode, tiledir="tiles", **qtree_args)
        else:
            qtree = quadtree.QuadtreeGen(w, destdir, rendermode=rendermode, **qtree_args)
        q.append(qtree)

    # do quadtree-level preprocessing
    for qtree in q:
        qtree.go(options.procs)

    # create the distributed render
    r = rendernode.RenderNode(q, options)

    # write out the map and web assets
    m = googlemap.MapGen(q, configInfo=options)
    m.go(options.procs)

    # render the tiles!
    r.go(options.procs)

    # finish up the map
    m.finalize()
    def _output_assets(self, tilesets, initial):
        if not initial:
            get_data = lambda tileset: tileset.get_persistent_data()
        else:
            get_data = lambda tileset: tileset.get_initial_data()

        # dictionary to hold the overviewerConfig.js settings that we will dumps
        dump = dict()
        dump['CONST'] = dict(tileSize=384)
        dump['CONST']['image'] = {
            'defaultMarker':
            'signpost.png',
            'signMarker':
            'signpost_icon.png',
            'compass':
            '******',
            'spawnMarker':
            'http://google-maps-icons.googlecode.com/files/home.png',
            'queryMarker':
            'http://google-maps-icons.googlecode.com/files/regroup.png'
        }
        dump['CONST']['mapDivId'] = 'mcmap'
        dump['CONST']['regionStrokeWeight'] = 2
        dump['CONST']['UPPERLEFT'] = world.UPPER_LEFT
        dump['CONST']['UPPERRIGHT'] = world.UPPER_RIGHT
        dump['CONST']['LOWERLEFT'] = world.LOWER_LEFT
        dump['CONST']['LOWERRIGHT'] = world.LOWER_RIGHT

        # based on the tilesets we have, group them by worlds
        worlds = []
        for tileset in tilesets:
            full_name = get_data(tileset)['world']
            if full_name not in worlds:
                worlds.append(full_name)

        dump['worlds'] = worlds
        dump['map'] = dict()
        dump['map']['debug'] = True
        dump['map']['cacheTag'] = str(int(time.time()))
        dump['map']['north_direction'] = 'lower-left'  # only temporary
        dump['map']['center'] = [-314, 67, 94]
        dump['map']['controls'] = {
            'pan': True,
            'zoom': True,
            'spawn': True,
            'compass': True,
            'mapType': True,
            'overlays': True,
            'coordsBox': True,
            'searchBox': True
        }

        dump['tilesets'] = []

        for tileset in tilesets:
            dump['tilesets'].append(get_data(tileset))

            # write a blank image
            blank = Image.new("RGBA", (1, 1), tileset.options.get('bgcolor'))
            blank.save(
                os.path.join(self.outputdir, tileset.options.get('name'),
                             "blank." + tileset.options.get('imgformat')))

        # copy web assets into destdir:
        global_assets = os.path.join(util.get_program_path(),
                                     "overviewer_core", "data", "web_assets")
        if not os.path.isdir(global_assets):
            global_assets = os.path.join(util.get_program_path(), "web_assets")
        mirror_dir(global_assets, self.outputdir)

        # write a dummy baseMarkers.js if none exists
        if not os.path.exists(os.path.join(self.outputdir, "baseMarkers.js")):
            with open(os.path.join(self.outputdir, "baseMarkers.js"),
                      "w") as f:
                f.write("// if you wants signs, please see genPOI.py\n")

        # create overviewer.js from the source js files
        js_src = os.path.join(util.get_program_path(), "overviewer_core",
                              "data", "js_src")
        if not os.path.isdir(js_src):
            js_src = os.path.join(util.get_program_path(), "js_src")
        with FileReplacer(os.path.join(self.outputdir,
                                       "overviewer.js")) as tmpfile:
            with open(tmpfile, "w") as fout:
                # first copy in js_src/overviewer.js
                with open(os.path.join(js_src, "overviewer.js"), 'r') as f:
                    fout.write(f.read())
                # now copy in the rest
                for js in os.listdir(js_src):
                    if not js.endswith("overviewer.js") and js.endswith(".js"):
                        with open(os.path.join(js_src, js)) as f:
                            fout.write(f.read())

        # write out config
        jsondump = json.dumps(dump, indent=4)
        with FileReplacer(os.path.join(self.outputdir,
                                       "overviewerConfig.js")) as tmpfile:
            with codecs.open(tmpfile, 'w', encoding='UTF-8') as f:
                f.write("var overviewerConfig = " + jsondump + ";\n")

        # Add time and version in index.html
        indexpath = os.path.join(self.outputdir, "index.html")

        index = codecs.open(indexpath, 'r', encoding='UTF-8').read()
        index = index.replace("{title}", "Minecraft Overviewer")
        index = index.replace(
            "{time}",
            time.strftime("%a, %d %b %Y %H:%M:%S %Z", time.localtime()).decode(
                locale.getpreferredencoding()))
        versionstr = "%s (%s)" % (util.findGitVersion(),
                                  util.findGitHash()[:7])
        index = index.replace("{version}", versionstr)

        with FileReplacer(indexpath) as indexpath:
            with codecs.open(indexpath, 'w', encoding='UTF-8') as output:
                output.write(index)
    def _output_assets(self, tilesets, initial):
        if not initial:
            get_data = lambda tileset: tileset.get_persistent_data()
        else:
            get_data = lambda tileset: tileset.get_initial_data()

        # dictionary to hold the overviewerConfig.js settings that we will dumps
        dump = dict()
        dump['CONST'] = dict(tileSize=384)
        dump['CONST']['image'] = {
                'defaultMarker':    'signpost.png',
                'signMarker':       'signpost_icon.png',
                'compass':          '******',
                'spawnMarker':      'http://google-maps-icons.googlecode.com/files/home.png',
                'queryMarker':      'http://google-maps-icons.googlecode.com/files/regroup.png'
                }
        dump['CONST']['mapDivId'] = 'mcmap'
        dump['CONST']['regionStrokeWeight'] = 2
        dump['CONST']['UPPERLEFT']  = world.UPPER_LEFT;
        dump['CONST']['UPPERRIGHT'] = world.UPPER_RIGHT;
        dump['CONST']['LOWERLEFT']  = world.LOWER_LEFT;
        dump['CONST']['LOWERRIGHT'] = world.LOWER_RIGHT;

        # based on the tilesets we have, group them by worlds
        worlds = []
        for tileset in tilesets:
            full_name = get_data(tileset)['world']
            if full_name not in worlds:
                worlds.append(full_name)

        dump['worlds'] = worlds
        dump['map'] = dict()
        dump['map']['debug'] = True
        dump['map']['cacheTag'] = str(int(time.time()))
        dump['map']['north_direction'] = 'lower-left' # only temporary
        dump['map']['center'] = [-314, 67, 94]
        dump['map']['controls'] = {
            'pan': True,
            'zoom': True,
            'spawn': True,
            'compass': True,
            'mapType': True,
            'overlays': True,
            'coordsBox': True,
            'searchBox': True
            }


        dump['tilesets'] = []


        for tileset in tilesets:
            dump['tilesets'].append(get_data(tileset))

            # write a blank image
            blank = Image.new("RGBA", (1,1), tileset.options.get('bgcolor'))
            blank.save(os.path.join(self.outputdir, tileset.options.get('name'), "blank." + tileset.options.get('imgformat')))


        # copy web assets into destdir:
        global_assets = os.path.join(util.get_program_path(), "overviewer_core", "data", "web_assets")
        if not os.path.isdir(global_assets):
            global_assets = os.path.join(util.get_program_path(), "web_assets")
        mirror_dir(global_assets, self.outputdir)

		# write a dummy baseMarkers.js if none exists
        if not os.path.exists(os.path.join(self.outputdir, "baseMarkers.js")):
            with open(os.path.join(self.outputdir, "baseMarkers.js"), "w") as f:
                f.write("// if you wants signs, please see genPOI.py\n");


        # create overviewer.js from the source js files
        js_src = os.path.join(util.get_program_path(), "overviewer_core", "data", "js_src")
        if not os.path.isdir(js_src):
            js_src = os.path.join(util.get_program_path(), "js_src")
        with FileReplacer(os.path.join(self.outputdir, "overviewer.js")) as tmpfile:
            with open(tmpfile, "w") as fout:
                # first copy in js_src/overviewer.js
                with open(os.path.join(js_src, "overviewer.js"), 'r') as f:
                    fout.write(f.read())
                # now copy in the rest
                for js in os.listdir(js_src):
                    if not js.endswith("overviewer.js") and js.endswith(".js"):
                        with open(os.path.join(js_src,js)) as f:
                            fout.write(f.read())
        
        # write out config
        jsondump = json.dumps(dump, indent=4)
        with FileReplacer(os.path.join(self.outputdir, "overviewerConfig.js")) as tmpfile:
            with codecs.open(tmpfile, 'w', encoding='UTF-8') as f:
                f.write("var overviewerConfig = " + jsondump + ";\n")
        
        # Add time and version in index.html
        indexpath = os.path.join(self.outputdir, "index.html")

        index = codecs.open(indexpath, 'r', encoding='UTF-8').read()
        index = index.replace("{title}", "Minecraft Overviewer")
        index = index.replace("{time}", time.strftime("%a, %d %b %Y %H:%M:%S %Z", time.localtime()).decode(locale.getpreferredencoding()))
        versionstr = "%s (%s)" % (util.findGitVersion(), util.findGitHash()[:7])
        index = index.replace("{version}", versionstr)

        with FileReplacer(indexpath) as indexpath:
            with codecs.open(indexpath, 'w', encoding='UTF-8') as output:
                output.write(index)