18 Star 1 Fork 3

openKylin / packaging-tools

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
source-packing.py 14.68 KB
一键复制 编辑 原始数据 按行查看 历史
luoyaoming 提交于 2022-10-25 20:04 . first commit
#! /usr/bin/python3
# depends python3-magic, git-buildpackage, python3-debian
import argparse
import os
import glob
import shutil
import configparser
import time
from debian.changelog import Changelog, get_maintainer
import subprocess as p
import magic
from gbp.deb.dscfile import DscFile
def xz_to_gz(fn: str) -> str:
new_fn = f"{os.path.splitext(fn)[0]}.gz"
p.check_call(f"xzcat {fn} | gzip -c - > {new_fn}", shell=True)
os.remove(fn)
return new_fn
def gz_to_xz(fn: str) -> str:
new_fn = f"{os.path.splitext(fn)[0]}.xz"
p.check_call(f"zcat {fn} | xz -c - > {new_fn}", shell=True)
os.remove(fn)
return new_fn
class Package:
dsc_file = source_path = ""
def __init__(self, dsc_file: str = "", source_path: str = "") -> None:
assert (
dsc_file != "" or source_path != ""
), "you must specify a dsc file or exact source path"
availed_path_str = dsc_file if dsc_file else source_path
self.file_path = os.path.dirname(os.path.realpath(availed_path_str))
if dsc_file and not source_path:
self.dsc_file = dsc_file
self.exact_source()
if source_path:
self.source_path = source_path
self._parse_source_info()
self._parse_dsc_file()
def _parse_dsc_file(self):
if not self.dsc_file:
self.dsc_file = glob.glob(
f"{self.file_path}/*_%s.dsc"
% self.changelog_info.full_version.split(":")[-1]
)[0]
self.gbp_dsc = DscFile(self.dsc_file)
self.additional_tarballs = self.gbp_dsc.additional_tarballs
def _parse_source_info(self):
with open(os.path.join(self.source_path, "debian/changelog"), "rb") as f:
self.changelog_info = Changelog(file=f)
self.old_version = self.changelog_info.full_version
format_file = os.path.join(self.source_path, "debian/source/format")
if os.path.exists(format_file):
format = open(format_file).read().strip()
self.source_format = "native" if format != "3.0 (quilt)" else "quilt"
else:
self.source_format = "native"
@property
def is_quilt(self) -> bool:
return self.source_format == "quilt"
def exact_source(self):
if getattr(self, "source_path", ""):
return
tmp_source_path = f"rebuild_tmp_source_{time.time()}"
p.check_call(
f"dpkg-source -x {self.dsc_file} {tmp_source_path}",
shell=True,
cwd=self.file_path,
)
self.source_path = os.path.join(self.file_path, tmp_source_path)
self._parse_source_info()
def change_format(self):
debian_source = os.path.join(self.source_path, "debian/source")
if not os.path.exists(debian_source):
os.makedirs(debian_source)
# switch to quilt
format_file = os.path.join(debian_source, "format")
with open(format_file, "w") as f:
f.write("3.0 (quilt)\n")
def add_gbp_conf(self):
if self.additional_tarballs:
self.gbp_conf = os.path.join(self.source_path, "debian/gbp.conf")
cp = configparser.ConfigParser()
cp.read(self.gbp_conf, encoding="utf-8")
if not cp.has_section("buildpackage"):
cp.add_section("buildpackage")
values = list(self.additional_tarballs.keys())
if len(values) == 1:
values = values[0]
else:
_tmp_values = "','".join(values)
values = f"[{_tmp_values}]"
if not cp.has_option("buildpackage", "component"):
cp.set("buildpackage", "component", values)
with open(self.gbp_conf, "w+") as f:
cp.write(f)
def fix_additional_tarballs_comp_format(self):
# check orig tarballs compres type
tgz_comp_type = magic.from_file(self.gbp_dsc.tgz, mime=True)
is_xz = "x-xz" in tgz_comp_type
is_gz = "gzip" in tgz_comp_type
# is_bz =
for fn in self.additional_tarballs.values():
if magic.from_file(fn, mime=True) != tgz_comp_type:
# do recompres
new_fn = fn
if is_xz:
new_fn = gz_to_xz(fn)
elif is_gz:
new_fn = xz_to_gz(fn)
else:
raise Exception(f"no support compress type for {tgz_comp_type}")
# shutil.move(new_fn, self.source_path)
def build_changelog(
self,
new_revisions: str = "",
save_old_changes: bool = True,
suite: str = "",
changes: str = "",
):
user, email = get_maintainer()
revisions = (
new_revisions if new_revisions else self.changelog_info.debian_revision
)
v = self.changelog_info.get_version()
setattr(v, "debian_revision", revisions)
suite = self.changelog_info.distributions if not suite else suite
self.changelog_info.new_block(
package=self.changelog_info.package,
version=v,
distributions=suite,
urgency=self.changelog_info.urgency,
author=f"{user} <{email}>",
date=time.strftime("%a, %d %b %Y %H:%M:%S %z"),
)
self.changelog_info.add_change("")
self.changelog_info.add_change(f" * {changes}")
self.changelog_info.add_change("")
if not save_old_changes:
os.remove(os.path.join(self.source_path, "debian/changelog"))
self.changelog_info._blocks[:1]
with open(os.path.join(self.source_path, "debian/changelog"), "w") as f:
self.changelog_info.write_to_open_file(f)
def rebuild_source(self, args):
new_revisions = "" if not args.new_revisions else args.new_revisions
if not self.is_quilt:
new_revisions = new_revisions if new_revisions else "1"
self.change_format()
p.call(["rm", "-rf" "debian/patches/series"], cwd=self.source_path)
pc = os.path.join(self.source_path, ".pc")
if os.path.exists(pc):
shutil.rmtree(pc)
self.build_changelog(
suite=args.suite,
new_revisions=new_revisions,
save_old_changes=args.save_old_changes,
changes="修改为quilt格式",
)
p.check_call(
["debmake", "-y", "-t", "-u", self.changelog_info.upstream_version],
cwd=self.source_path,
)
elif new_revisions:
self.build_changelog(
suite=args.suite,
new_revisions=new_revisions,
save_old_changes=args.save_old_changes,
changes="rebuild source for openKylin",
)
self.add_gbp_conf()
self.fix_additional_tarballs_comp_format()
p.check_call("dpkg-source -b .", shell=True, cwd=self.source_path)
self.orig_dsc_file = self.dsc_file
self.dsc_file = self.dsc_file.replace(self.old_version, self.changelog_info.full_version)
return os.path.abspath(self.dsc_file)
def rebuild_source(args: argparse.Namespace):
pkg = Package(dsc_file=args.dsc_file, source_path=args.source_path)
try:
pkg.rebuild_source(args=args)
except Exception as e:
print(e)
finally:
shutil.rmtree(pkg.source_path)
def import_to_git(args):
branch = args.packaging_branch
dsc = args.dsc_file
assert os.path.exists(dsc), f"no such {dsc} file"
DSC = DscFile(dsc)
p.check_call(
f"gbp import-dsc --pristine-tar --debian-branch={branch} --create-missing-branches --upstream-branch=upstream {dsc} {DSC.pkg}",
shell=True,
)
os.chdir(DSC.pkg)
p.check_call(f"git checkout {branch}", shell=True)
p.check_call(f"git checkout -b packaging/{branch}", shell=True)
p.check_call("gbp pq import", shell=True)
p.check_call("gbp pq export", shell=True)
p.check_call("git add debian", shell=True)
p.check_call('git commit -m "format patches" || true', shell=True)
p.check_call(f"git checkout {branch}", shell=True)
p.check_call(
f'git merge patch-queue/packaging/{branch} -m "apply patches"', shell=True
)
p.check_call(f"git branch -D patch-queue/packaging/{branch}", shell=True)
patches = os.path.join(DSC.pkg, "debian/patches")
if os.path.exists(patches):
shutil.rmtree(patches)
p.check_call('echo "3.0 (native)" > debian/source/format', shell=True)
p.check_call("git add debian", shell=True)
p.check_call('git commit -m "changed debian/source/format to native"', shell=True)
def confirm(content: str, result: list = ["y", "n", "yes", "no"]) -> str:
print(content, end="")
_result = input()
if _result.lower() not in result:
confirm(content=content)
return _result
def import_branch(args):
packaging_branch = args.packaging_branch
dsc = args.dsc_file
repo = args.repo_path
git_repo = args.git_repo
derived_branch = args.derived_branch
if git_repo:
try:
repo = git_repo.split("/")[-1].split(".")[0]
# repo = os.path.join()
except:
raise Exception(f"{git_repo} is not a valid git url")
p.check_call(f"git clone {git_repo} {repo}", shell=True)
assert repo and os.path.exists(repo), f"no such directory for {repo}"
assert os.path.exists(os.path.join(repo, ".git")), f"{repo} is not a valid git repo"
assert packaging_branch, f"please specify debian branch"
p.check_call(
'git branch -r | \
grep -v "\->" | \
while read remote; \
do git branch --track "${remote#origin/}" "$remote"; \
done || \
true',
shell=True,
cwd=repo,
)
repo_branches = (
p.check_output(f'git checkout upstream && git branch -a |grep -v -E "^remotes"', shell=True, cwd=repo)
.decode("utf-8")
.splitlines()
)
if packaging_branch in [b.strip() for b in repo_branches if b]:
result = confirm(
f"## {packaging_branch} branch already exists, whether to rebuild? [Y/N]: "
)
if result in ["n", "no"]:
return print("## exit. no change.")
else:
p.check_call(
f"git checkout upstream && git branch -D {packaging_branch} -D packaging/{packaging_branch} || true",
shell=True,
cwd=repo,
)
if derived_branch:
p.check_call(f"git checkout {derived_branch}", shell=True, cwd=repo)
p.check_call(f"git checkout -b {packaging_branch}", shell=True, cwd=repo)
p.check_call(f"git checkout packaging/{derived_branch}", shell=True, cwd=repo)
p.check_call(
f"git checkout -b packaging/{packaging_branch}", shell=True, cwd=repo
)
else:
setattr(args, "new_revisions", "")
setattr(args, "suite", "")
setattr(args, "save_old_changes", "")
pkg = Package(dsc_file=dsc, source_path="")
# rebuild source
new_dsc = pkg.rebuild_source(args=args)
p.check_call(
f"gbp import-dsc --pristine-tar \
--debian-branch={packaging_branch} \
--create-missing-branches \
--upstream-branch=upstream {new_dsc}",
shell=True,
cwd=repo,
)
p.check_call(
"git restore --staged . && \
git clean -f -d",
shell=True,
cwd=repo,
)
p.check_call(
f"git checkout {packaging_branch} && \
git branch packaging/{packaging_branch}",
shell=True,
cwd=repo,
)
p.check_call(
"gbp pq import && gbp pq switch",
shell=True,
cwd=repo,
)
p.check_call(
f"git merge patch-queue/{packaging_branch} && \
git branch -D patch-queue/{packaging_branch}",
shell=True,
cwd=repo,
)
p.check_call(
"rm -rf debian/patches && \
echo '3.0 (native)' > debian/source/format && \
git add . && \
git commit -m 'change format'",
shell=True,
cwd=repo,
)
if __name__ == "__main__":
arg = argparse.ArgumentParser()
sub_parser = arg.add_subparsers()
rebuild_source_parser = sub_parser.add_parser(
"rebuild-source", help="rebuild source from debian source"
)
rebuild_source_parser.add_argument(
"-d",
"--dsc-file", dest="dsc_file", help="the dsc file full path"
)
rebuild_source_parser.add_argument(
"-p",
"--source-path", dest="source_path", help="the debian source path with exacted"
)
rebuild_source_parser.add_argument(
"-s",
"--suite", dest="suite", help="distribution suite"
)
rebuild_source_parser.add_argument(
"--save-old-changes",
dest="save_old_changes",
action="store_true",
default=False,
help="save old changes",
)
rebuild_source_parser.add_argument(
"-n",
"--new-revisions",
dest="new_revisions",
help="the revisions would replace the old revisions",
)
rebuild_source_parser.set_defaults(func=rebuild_source)
import_to_git_parser = sub_parser.add_parser(
"import-to-git", help="import debian source to git repo"
)
import_to_git_parser.add_argument(
"-b",
"--packaging-branch",
dest="packaging_branch",
default="openkylin/yangtze",
help="the git branch for openkylin packaging",
)
import_to_git_parser.add_argument(
"-d",
"--dsc-file", required=True, dest="dsc_file", help="the dsc file"
)
import_to_git_parser.set_defaults(func=import_to_git)
import_branch_parser = sub_parser.add_parser(
"import-branch",
help="import debian source as a new debian branch for exists git repo",
)
import_branch_parser.add_argument(
"-b",
"--packaging-branch",
dest="packaging_branch",
required=True,
help="the git branch for openkylin packaging",
)
import_branch_parser.add_argument(
"-p",
"--repo-path",
dest="repo_path",
help="the exists git repo path for import to new branch",
)
import_branch_parser.add_argument(
"-u",
"--git-url",
dest="git_repo",
help="the exists git repo url to clone for import to new branch",
)
import_branch_parser.add_argument(
"--derived-branch", dest="derived_branch", help="derived branch"
)
import_branch_parser.add_argument(
"-d",
"--dsc-file", dest="dsc_file", help="the dsc file"
)
import_branch_parser.set_defaults(func=import_branch)
args = arg.parse_args()
args.func(args)
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/openkylin/packaging-tools.git
git@gitee.com:openkylin/packaging-tools.git
openkylin
packaging-tools
packaging-tools
master

搜索帮助

344bd9b3 5694891 D2dac590 5694891