196 lines
5.9 KiB
Python
196 lines
5.9 KiB
Python
#!/usr/bin/env python3
|
|
|
|
# Copyright (C) 2023 The C++ Plus Project.
|
|
# This file is part of the cppp library.
|
|
#
|
|
# The cppp library is free software; you can redistribute it
|
|
# and/or modify it under the terms of the GNU Lesser General Public
|
|
# License as published by the Free Software Foundation; either version 3
|
|
# of the License, or (at your option) any later version.
|
|
#
|
|
# The cppp library is distributed in the hope that it will be
|
|
# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
# Lesser General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU Lesser General Public
|
|
# License along with the cppp library; see the file COPYING.
|
|
# If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
# C++ Plus dist utils.
|
|
|
|
import os
|
|
import sys
|
|
import json
|
|
import shutil
|
|
import importlib.util
|
|
|
|
PACKAGE_INFO = "CPPPPKG"
|
|
PROGNAME = "cpppdist.py"
|
|
|
|
def import_file(path):
|
|
"""
|
|
Import a Python file from it's path
|
|
|
|
Args:
|
|
path (str): Python file's path
|
|
|
|
Raises:
|
|
ModuleNotFoundError: When module invalid, load error or not found.
|
|
|
|
Returns:
|
|
ModuleType: module
|
|
"""
|
|
spec = importlib.util.spec_from_file_location(os.path.basename(path).replace(".py", ""), path)
|
|
if(spec == None):
|
|
raise ModuleNotFoundError("Invalid module or module not found: " + path)
|
|
module = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(module)
|
|
return module
|
|
|
|
class Package:
|
|
"""
|
|
A dist package type
|
|
"""
|
|
name = ""
|
|
version = ""
|
|
list_file_path = ""
|
|
filelist = []
|
|
subpackages = {}
|
|
|
|
def __init__(self, pkginfo_filepath) -> None:
|
|
try:
|
|
os.chdir(fwd)
|
|
with open(pkginfo_filepath, "r", encoding="UTF-8") as info_file:
|
|
data = json.load(info_file)
|
|
self.name = data["name"]
|
|
self.version = data["version"]
|
|
self.list_file_path = data["list_file_path"]
|
|
try:
|
|
_subpackages = data["subpackages"]
|
|
for pkgname in _subpackages:
|
|
pkgpath = _subpackages[pkgname]["path"]
|
|
try:
|
|
pkgmodule = import_file(os.path.join(pkgpath, PROGNAME))
|
|
self.subpackages[pkgpath] = pkgmodule.package
|
|
except Exception as e:
|
|
if(not _subpackages[pkgname]["ignore"]):
|
|
raise
|
|
else:
|
|
print(f"DEBUG: Ignore a subpackage '{pkgname}': {e}", file=sys.stderr)
|
|
except KeyError:
|
|
pass
|
|
self.filelist = self.get_file_list()
|
|
finally:
|
|
os.chdir(cwd)
|
|
|
|
def get_file_list(self) -> list:
|
|
"""
|
|
Get file list for dist.
|
|
"""
|
|
try:
|
|
os.chdir(fwd)
|
|
file_list = []
|
|
with open(self.list_file_path, "rt", encoding="UTF-8") as list_file:
|
|
data = list_file.read()
|
|
file_list = data.strip().split("\n")
|
|
return file_list
|
|
finally:
|
|
os.chdir(cwd)
|
|
|
|
def copy_files(self, dest):
|
|
"""
|
|
Copy files to dist dest
|
|
"""
|
|
try:
|
|
os.chdir(fwd)
|
|
if(os.path.exists(dest)):
|
|
shutil.rmtree(dest)
|
|
print(f"Copy package '{self.name}' to '{dest}' ... ", file=sys.stderr)
|
|
progressbar = ProgressBar(len(self.filelist))
|
|
for file in self.filelist:
|
|
relpath = os.path.relpath(file, fwd)
|
|
filedir = os.path.abspath(os.path.join(dest, relpath, ".."))
|
|
if(not os.path.exists(filedir)):
|
|
os.makedirs(filedir)
|
|
shutil.copy(file, os.path.join(dest, relpath))
|
|
progressbar.add(1)
|
|
progressbar.end()
|
|
print("", end="\n", file=sys.stderr)
|
|
# Copy subpackages
|
|
for (pkgpath, pkg) in self.subpackages.items():
|
|
pkg.copy_files(os.path.join(dest, os.path.join(dest, pkgpath)))
|
|
finally:
|
|
os.chdir(cwd)
|
|
|
|
class ProgressBar:
|
|
"""
|
|
Progress bar type.
|
|
"""
|
|
def __init__(self, total):
|
|
self.total = total
|
|
self.cur = 0
|
|
sys.stderr.write("\n")
|
|
self.update()
|
|
|
|
def add(self, step):
|
|
"""
|
|
Add current value and update.
|
|
"""
|
|
self.cur += step
|
|
self.update()
|
|
|
|
def set(self, cur):
|
|
"""
|
|
Set current value and update.
|
|
"""
|
|
self.cur = cur
|
|
self.update()
|
|
|
|
def update(self):
|
|
"""
|
|
Update progress bar.
|
|
"""
|
|
try:
|
|
progress = 0.0
|
|
if(self.cur):
|
|
progress = self.cur / self.total
|
|
term_width = os.get_terminal_size(sys.stderr.fileno()).columns
|
|
part_width = term_width - len("[]100.0%")
|
|
if(part_width <= 0):
|
|
# Terminal is too small, ignore.
|
|
return
|
|
sys.stderr.write("\r")
|
|
# Part1 is '#'
|
|
part1 = int(part_width * progress) * '#'
|
|
# Part2 is ' '
|
|
part2 = int(part_width - len(part1)) * ' '
|
|
# Part3 is 'xxx.x%'
|
|
part3 = str(int(progress * 1000) / 10) + "%"
|
|
sys.stderr.write(f"[{part1}{part2}]{part3}")
|
|
sys.stderr.flush()
|
|
except:
|
|
return
|
|
|
|
def end(self):
|
|
"""
|
|
End this progress bar
|
|
"""
|
|
self.set(self.total)
|
|
sys.stderr.write("\n")
|
|
sys.stderr.flush()
|
|
|
|
cwd = os.path.abspath(os.curdir)
|
|
fwd = os.path.abspath(os.path.join(__file__, ".."))
|
|
|
|
package = None
|
|
try:
|
|
package = Package(PACKAGE_INFO)
|
|
except Exception as exc:
|
|
print("Getting packge infomation error:", exc, file=sys.stderr)
|
|
raise exc
|
|
|
|
if __name__ == "__main__":
|
|
distdir = f"{package.name}-v{package.version}"
|
|
package.copy_files(os.path.abspath(distdir))
|