如何对用户可修改的配置 JSON 文件进行版本控制?

How to version user-modifiable config JSON file?

我有多个 JSON 文件与我的 Python PyPI package 打包在一起。这些 JSON 文件作为配置文件从源分发版复制到用户主目录下的 .ec2mc/ 目录。顶级配置 JSON 文件 (aws_setup.json) 设计为可由用户修改。

我如何设置才能覆盖旧的配置版本,除非用户对配置进行了自己的修改?

我目前的设置是在 aws_setup.json 中添加 Version (int) 和 Protect (bool) 密钥,Version 密钥用于在更新分发时更新配置,而 Protect 密钥用于用户防止配置被覆盖。逻辑如下:

# The config's aws_setup.json must have the "Protect" and "Version" keys
if not all(key in config_aws_setup for key in ("Protect", "Version")):
    cp_aws_setup_to_config(aws_setup_src_dir)
# If the "Protect" key has been set to True, prevent overwriting aws_setup
elif config_aws_setup["Protect"]:
    pass
# Version can be set to 0 during development for constant refreshing
elif source_aws_setup["Version"] == 0:
    cp_aws_setup_to_config(aws_setup_src_dir)
# Update if aws_setup_src has larger version number
elif source_aws_setup["Version"] > config_aws_setup["Version"]:
    cp_aws_setup_to_config(aws_setup_src_dir)

cp_aws_setup_to_config 函数用发行版本覆盖配置:

def cp_aws_setup_to_config(aws_setup_src_dir):
    if os.path.isdir(config.AWS_SETUP_DIR):
        shutil.rmtree(config.AWS_SETUP_DIR)
    shutil.copytree(aws_setup_src_dir, config.AWS_SETUP_DIR)

虽然它有效,但我觉得这个设置有点复杂,并且希望获得一些更简单的方法来实现相同效果的建议。

发行版的模板配置和用户的配置可以通过文件比较来比较,前提是它们同时存在于同一个系统上。 filecmp 的 cmpfiles 是理想的选择,因为它可以比较相似目录结构中的文件。

def recursive_cmpfiles(src_dir, dest_dir):
    """wrapper for filecmp.cmpfiles, which recursively finds src_dir's files"""
    prefix_len = len(src_dir.parts)
    cmp_files = []
    for path, _, files in os.walk(src_dir):
        for f in files:
            cmp_files.append(Path(*(Path(path) / f).parts[prefix_len:]))
    return filecmp.cmpfiles(src_dir, dest_dir, cmp_files, shallow=False)

# If 'Modified' key is True, prevent overwriting config's aws_setup
if config_aws_setup['Modified'] is False:
    diffs = os2.recursive_cmpfiles(aws_setup_dir_src, aws_setup_dir_dest)
    # If source and dest aws_setup differ, overwrite dest aws_setup
    # If dest aws_setup missing files, overwrite dest aws_setup
    if diffs[1] or diffs[2]:
        cp_aws_setup_to_config(aws_setup_dir_src)

虽然仍然使用 'Protect'(现在 'Modified')键,但这样就不再需要 Version 键了。