예제 #1
0
def create_patch(dir_src,
                 dir_all_release,
                 create_patch_for_latest_n_version,
                 dir_github_action_artifact,
                 get_final_patch_path_only=False) -> str:
    latest_version = now_version
    path_bz = os.path.join(dir_src, "utils/bandizip_portable", "bz.exe")

    old_cwd = os.getcwd()
    os.chdir(dir_all_release)
    if not get_final_patch_path_only:
        logger.info(f"工作目录已调整为{os.getcwd()},最新版本为v{latest_version}")

    uploader = Uploader()

    if not get_final_patch_path_only:
        logger.info(
            f"尝试从网盘查找在{latest_version}版本之前最近{create_patch_for_latest_n_version}个版本的信息"
        )
    old_version_infos = []  # type: List[HistoryVersionFileInfo]

    # 获取当前网盘的最新版本,若比当前发布版本低,也加入
    netdisk_latest_version_fileinfo = uploader.find_latest_version()
    netdisk_latest_version = uploader.parse_version_from_djc_helper_file_name(
        netdisk_latest_version_fileinfo.name)
    if version_less(netdisk_latest_version, latest_version):
        old_version_infos.append(
            HistoryVersionFileInfo(netdisk_latest_version_fileinfo,
                                   netdisk_latest_version))

    # 从历史版本网盘中查找旧版本
    for page in range_from_one(100):
        folder_info = uploader.get_folder_info_by_url(
            uploader.folder_history_files.url, get_this_page=page)
        for file in folder_info.files:
            filename = file.name  # type: str

            if not filename.startswith(uploader.history_version_prefix):
                # 跳过非历史版本的文件
                continue

            file_version = uploader.parse_version_from_djc_helper_file_name(
                filename)
            info = HistoryVersionFileInfo(file, file_version)

            if not version_less(file_version, latest_version):
                continue

            if info in old_version_infos:
                # 已经加入过(可能重复)
                continue

            old_version_infos.append(info)

        if len(old_version_infos) >= create_patch_for_latest_n_version + 2:
            # 已经找到超过前n+2个版本,因为网盘返回的必定是按上传顺序排列的,不过为了保险起见,多考虑一些
            break

    if create_patch_for_latest_n_version > len(old_version_infos):
        create_patch_for_latest_n_version = len(old_version_infos)

    old_version_infos = sorted(
        old_version_infos)[-create_patch_for_latest_n_version:]

    # 确认最终文件名
    patch_oldest_version = old_version_infos[0].version
    patch_newest_version = old_version_infos[-1].version
    patches_dir = f"DNF蚊子腿小助手_增量更新文件_v{patch_oldest_version}_to_v{patch_newest_version}"
    temp_dir = "patches_temp"

    patch_7z_file = f"{patches_dir}.7z"
    if get_final_patch_path_only:
        return patch_7z_file

    logger.info(f"需要制作补丁包的版本为{old_version_infos}")

    # 确保版本都在本地
    logger.info(f"确保以上版本均已下载并解压到本地~")
    for info in old_version_infos:
        local_folder_path = os.path.join(dir_all_release,
                                         f"DNF蚊子腿小助手_v{info.version}_by风之凌殇")
        local_7z_path = local_folder_path + ".7z"

        if os.path.isdir(local_folder_path):
            # 本地已存在对应版本,跳过
            continue

        logger.info(f"本地发布目录不存在 {local_folder_path}")
        if not os.path.isfile(local_7z_path):
            logger.info(f"本地不存在{info.fileinfo.name}的7z文件,将从网盘下载")
            uploader.download_file(info.fileinfo, dir_all_release)

        logger.info(f"尝试解压 {info.fileinfo.name} 到 {local_folder_path}")
        decompress_dir_with_bandizip(local_7z_path, dir_src)

    # --------------------------- 实际只做补丁包 ---------------------------
    logger.info(color("bold_yellow") + f"将为【{old_version_infos}】版本制作补丁包")

    shutil.rmtree(patches_dir, ignore_errors=True)
    os.mkdir(patches_dir)
    shutil.rmtree(temp_dir, ignore_errors=True)
    os.mkdir(temp_dir)

    def temp_path(dir_name):
        return os.path.realpath(os.path.join(temp_dir, dir_name))

    def preprocess_before_patch(temp_version_path):
        for filename in ["config.toml", "utils/auto_updater.exe"]:
            filepath = os.path.join(temp_version_path, filename)
            if os.path.isfile(filepath):
                os.remove(filepath)

    # 为旧版本创建patch文件
    target_version_dir = f"DNF蚊子腿小助手_v{latest_version}_by风之凌殇"
    logger.info(f"目标版本目录为{target_version_dir}")
    shutil.copytree(target_version_dir, temp_path(target_version_dir))
    preprocess_before_patch(temp_path(target_version_dir))

    for idx, version_info in enumerate(old_version_infos):
        version = version_info.version
        patch_file = f"{patches_dir}/{version}.patch"

        logger.info("-" * 80)
        logger.info(
            color("bold_yellow") +
            f"[{idx + 1}/{len(old_version_infos)}] 创建从v{version}升级到v{latest_version}的补丁{patch_file}"
        )

        version_dir = f"DNF蚊子腿小助手_v{version}_by风之凌殇"

        shutil.copytree(version_dir, temp_path(version_dir))
        preprocess_before_patch(temp_path(version_dir))

        subprocess.call([
            os.path.realpath(os.path.join(dir_src, "utils/hdiffz.exe")),
            f"-p-{multiprocessing.cpu_count()}",  # 设置系统最大cpu数
            os.path.realpath(os.path.join(temp_dir, version_dir)),
            os.path.realpath(os.path.join(temp_dir, target_version_dir)),
            patch_file,
        ])

        filesize = os.path.getsize(patch_file)
        logger.info(f"创建补丁{patch_file}结束,最终大小为{human_readable_size(filesize)}")

    # 移除临时目录
    shutil.rmtree(temp_dir, ignore_errors=True)

    # 压缩打包
    compress_dir_with_bandizip(patches_dir, patch_7z_file, dir_src)

    # 额外备份一份最新的供github action 使用
    shutil.copyfile(
        patch_7z_file,
        os.path.join(dir_github_action_artifact, 'djc_helper_patches.7z'))

    os.chdir(old_cwd)

    return patch_7z_file
예제 #2
0
def package(dir_src, dir_all_release, release_dir_name, release_7z_name, dir_github_action_artifact):
    old_cwd = os.getcwd()

    show_head_line(f"开始打包 {release_dir_name} 所需内容", color("bold_yellow"))

    # 确保发布根目录存在
    if not os.path.isdir(dir_all_release):
        os.mkdir(dir_all_release)
    # 并清空当前的发布版本目录
    dir_current_release = os.path.realpath(os.path.join(dir_all_release, release_dir_name))
    shutil.rmtree(dir_current_release, ignore_errors=True)
    os.mkdir(dir_current_release)

    logger.info(color("bold_yellow") + f"将部分内容从 {dir_src} 复制到 {dir_current_release} ")
    # 需要复制的文件与目录
    files_to_copy = []
    # 基于正则确定初始复制范围
    reg_wantted_file = r'.*\.(toml|md|txt|png|jpg|docx|url)$'
    for file in os.listdir('.'):
        if not re.search(reg_wantted_file, file, flags=re.IGNORECASE):
            continue
        files_to_copy.append(file)
    # 额外补充一些文件和目录
    files_to_copy.extend([
        "config.example.toml",
        "DNF蚊子腿小助手.exe",
        "DNF蚊子腿小助手配置工具.exe",
        "DNF蚊子腿小助手配置文件.bat",

        "使用教程",
        "付费指引",
        "相关信息",
        "utils",
    ])
    # 按顺序复制
    files_to_copy = sorted(files_to_copy)
    # 复制文件与目录过去
    for filename in files_to_copy:
        source = os.path.join(dir_src, filename)
        destination = os.path.join(dir_current_release, filename)
        if os.path.isdir(filename):
            logger.info(f"拷贝目录 {filename}")
            shutil.copytree(source, destination)
        else:
            logger.info(f"拷贝文件 {filename}")
            shutil.copyfile(source, destination)

    logger.info(color("bold_yellow") + "移动部分文件的位置和名称")
    files_to_move = [
        ("utils/auto_updater.exe", "utils/auto_updater_latest.exe"),
        ("CHANGELOG.MD", "相关信息/CHANGELOG.MD"),
        ("README.MD", "相关信息/README.MD"),
    ]
    for src_file, dst_file in files_to_move:
        src_file = os.path.join(dir_current_release, src_file)
        dst_file = os.path.join(dir_current_release, dst_file)

        logger.info(f"移动{src_file}到{dst_file}")
        shutil.move(src_file, dst_file)

    logger.info(color("bold_yellow") + "清除一些无需发布的内容")
    dir_to_filenames_need_remove = {
        ".": [
            *list(path.name for path in pathlib.Path(".").glob('requirements*.txt')),

            "config.toml.local",
            *list(path.name for path in pathlib.Path(".").glob('config.toml.github_action*')),
        ],
        "utils": [
            "logs", ".db", ".cached", ".first_run", ".log.filename",
            "buy_auto_updater_users.txt", "user_monthly_pay_info.txt", "notices.txt",

            *list(path.name for path in pathlib.Path("utils").glob('chrome_portable_*')),

            "upx.exe",
        ],
    }
    for dir_path, filenames in dir_to_filenames_need_remove.items():
        for filename in filenames:
            filepath = os.path.join(dir_current_release, f"{dir_path}/{filename}")
            if not os.path.exists(filepath):
                continue

            if os.path.isdir(filepath):
                logger.info(f"移除目录 {filepath}")
                shutil.rmtree(filepath, ignore_errors=True)
            else:
                logger.info(f"移除文件 {filepath}")
                os.remove(filepath)

    # 压缩打包
    os.chdir(dir_all_release)
    logger.info(color("bold_yellow") + "开始压缩打包")
    compress_dir_with_bandizip(release_dir_name, release_7z_name, dir_src)

    # 额外备份一份最新的供github action 使用
    shutil.copyfile(release_7z_name, os.path.join(dir_github_action_artifact, 'djc_helper.7z'))

    os.chdir(old_cwd)