[software development] 求救!在开发zpkg软件包格式时遇到大问题!
Tofloor
poster avatar
Zeta.
deepin
2024-01-12 21:16
Author

在测试安装zpkg软件包时遇到如下报错

Zero@Zero-PC:~/test$ sudo zpm-pkg install test.zpkg
Traceback (most recent call last):
  File "/usr/bin/zpm-pkg", line 169, in 
    main()
  File "/usr/bin/zpm-pkg", line 161, in main
    install_package(sys.argv[2])
  File "/usr/bin/zpm-pkg", line 69, in install_package
    pkglist = json.load(f)
  File "/usr/lib/python3.7/json/__init__.py", line 296, in load
    parse_constant=parse_constant, object_pairs_hook=object_pairs_hook, **kw)
  File "/usr/lib/python3.7/json/__init__.py", line 348, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python3.7/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python3.7/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

json格式为

{"name": "test", "version": "1.0", "author": "ZYH", "enable_install": "true"}

安装软件包的原理是:安装zpkg软件包时将软件包解压到/temp/软件包文件名 目录,并读取info.json内的包名和版本号写入/opt/zpm/pkglist.json, 将data内所有文件复制到/(根)目录,并将所有复制的文件地址写入到包名.json到/opt/zpm/packages内,并运行包内install.sh,

开源地址(可向我们提交pr):zpm-local: ZhongHongSoftwarePackageManager本地端 (gitee.com)

全部源代码


#!/usr/bin/env python3

import os
import sys
import json
import zipfile
import shutil

def make_package():
    # 读取info.json配置文件
    package_name = input("包名: ")
    version = input("版本号: ")
    author = input("作者: ")
    enable_install = input("是否启用install.sh (Y/N): ").lower() == 'y'

    info = {
        "name": package_name,
        "version": version,
        "author": author,
        "enable_install": enable_install
    }

    with open("info.json", "w") as f:
        json.dump(info, f)

    # 创建install.sh文件
    os.system('touch install.sh')

    # 创建空的data目录
    os.makedirs("data")
    os.system('touch data/.keep')

    print("包目录创建成功!")

def build_package():
    # 获取当前目录名作为包名
    package_name = os.path.basename(os.getcwd())

    # 压缩包名为zpkg的压缩文件
    with zipfile.ZipFile(f"{package_name}.zpkg", "w") as zp:
        for root, dirs, files in os.walk("."):
            for file in files:
                # 将所有文件添加到压缩包
                zp.write(os.path.join(root, file))

    print(f"{package_name}.zpkg 打包完成!")

def install_package(package_file):
    # 解压包到临时目录
    temp_dir = "/temp/"
    package_name = os.path.splitext(package_file)[0]
    extract_path = f"{temp_dir}{package_name}"
    os.makedirs(extract_path)

    with zipfile.ZipFile(package_file, "r") as zp:
        zp.extractall(extract_path)
  
    # 读取info.json文件
    with open(f"{extract_path}/info.json", "r") as f:
        info = json.load(f)
        package_name = info["name"]
        version = info["version"]
  
    # 写入opt/zpm/pkglist.json
    pkglist_path = "/opt/zpm/pkglist.json"

    pkglist = []
    if os.path.exists(pkglist_path):
        with open(pkglist_path, "r") as f:
            pkglist = json.load(f)
  
    pkglist.append({"name": package_name, "version": version})

    with open(pkglist_path, "w") as f:
        json.dump(pkglist, f)
  
    # 将data目录下的文件复制到根目录
    data_dir = f"{extract_path}/data"
    if os.path.exists(data_dir):
        for root, dirs, files in os.walk(data_dir):
            for file in files:
                file_path = os.path.join(root, file)

                # 获取目标路径,并创建其父目录
                dest_path = os.path.join("/", file_path.replace(data_dir, ""))
                dest_dir = os.path.dirname(dest_path)
                os.makedirs(dest_dir, exist_ok=True)
              
                # 复制文件
                shutil.copy(file_path, dest_path)
  
    # 写入包名.json到opt/zpm/packages
    package_json_path = f"/opt/zpm/packages/{package_name}.json"
    package_json = {"files": []}

    for root, dirs, files in os.walk(extract_path):
        for file in files:
            file_path = os.path.join(root, file)
            package_json["files"].append(file_path.replace(extract_path, ""))
  
    with open(package_json_path, "w") as f:
        json.dump(package_json, f)
  
    # 运行install.sh
    if info.get("enable_install", False):
        install_script = f"{extract_path}/install.sh"
        if os.path.isfile(install_script) and os.access(install_script, os.X_OK):
            os.system(f"sh {install_script}")
  
    print(f"{package_name} 安装完成!")

def uninstall_package(package_name):
    # 删除data目录下的文件
    package_json_path = f"/opt/zpm/packages/{package_name}.json"
  
    if os.path.exists(package_json_path):
        with open(package_json_path, "r") as f:
            package_json = json.load(f)
      
        for file_path in package_json["files"]:
            file_path = os.path.join("/", file_path)
            if os.path.exists(file_path):
                os.remove(file_path)

        # 删除pkglist.json中的卸载包
        pkglist_path = "/opt/zpm/pkglist.json"
        if os.path.exists(pkglist_path):
            with open(pkglist_path, "r") as f:
                pkglist = json.load(f)
          
            pkglist = [pkg for pkg in pkglist if pkg["name"] != package_name]

            with open(pkglist_path, "w") as f:
                json.dump(pkglist, f)
      
        # 删除包的配置文件
        os.remove(package_json_path)

        print(f"{package_name} 卸载完成!")
    else:
        print(f"{package_name} 未安装!")

def main():
    if len(sys.argv) < 2:
        print("用法: zpm-pkg [command] [options]")
        print("命令:")
        print("  make              创建zpkg包目录")
        print("  build             将当前目录打包为zpkg格式")
        print("  install [file]    安装zpkg软件包")
        print("  uninstall [name]  卸载软件包")
    else:
        command = sys.argv[1]

        if command == "make":
            make_package()
        elif command == "build":
            build_package()
        elif command == "install":
            if len(sys.argv) < 3:
                print("请指定要安装的zpkg文件!")
            else:
                install_package(sys.argv[2])
        elif command == "uninstall":
            if len(sys.argv) < 3:
                print("请指定要卸载的软件包名!")
            else:
                uninstall_package(sys.argv[2])

if __name__ == "__main__":
    main()

Reply Favorite View the author
All Replies
出售星辰之书的书商
Moderator
2024-01-12 21:24
#1

applaud

Reply View the author
Zeta.
deepin
2024-01-12 21:28
#2
出售星辰之书的书商

applaud

清欲哥哥帮帮我blush

Reply View the author
fslong
deepin beta test group
2024-01-12 21:52
#3

json库判定比较严格,必须标准json格式还要管编码什么的,看看json库的内容吧。

Reply View the author
兆兆嘟嘟嘟
deepin
2024-01-13 06:21
#4

这个格式将会是基础包格式(如deb、rpm、pacman、pkg等)还是特殊包格式(如玲珑、开明、flatpak、snap、nix、homebrew、guix等)?

Reply View the author
Zeta.
deepin
2024-01-13 08:39
#5
兆兆嘟嘟嘟

这个格式将会是基础包格式(如deb、rpm、pacman、pkg等)还是特殊包格式(如玲珑、开明、flatpak、snap、nix、homebrew、guix等)?

基础包格式

Reply View the author
Zeta.
deepin
2024-01-13 08:39
#6
fslong

json库判定比较严格,必须标准json格式还要管编码什么的,看看json库的内容吧。

好的谢谢

Reply View the author