start reworking of build scripts
This commit is contained in:
parent
90cd2b9200
commit
0bde1c9cc5
6 changed files with 265 additions and 74 deletions
108
build.py
Normal file → Executable file
108
build.py
Normal file → Executable file
|
@ -1,15 +1,101 @@
|
||||||
import sys
|
#! /usr/bin/python3
|
||||||
from pathlib import Path
|
import argparse
|
||||||
|
import pathlib
|
||||||
|
|
||||||
from build_scripts.build import build
|
from build_scripts.build import build
|
||||||
|
from build_scripts.build.config import FILENAME_TYPE_RAW_NAME, FILENAME_TYPE_PREPEND_AUTHOR
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description='Incrementally build LatexPackages with PyTeX')
|
||||||
|
input_group = parser.add_mutually_exclusive_group(required=True)
|
||||||
|
output_group = parser.add_mutually_exclusive_group()
|
||||||
|
input_group.add_argument(
|
||||||
|
'-s', '--source-dir',
|
||||||
|
metavar='SRC_DIR',
|
||||||
|
help='Relative or absolute path to source directory of .pysty or .pycls files',
|
||||||
|
type=pathlib.Path,
|
||||||
|
nargs='?',
|
||||||
|
default='./src',
|
||||||
|
dest='src_dir'
|
||||||
|
)
|
||||||
|
output_group.add_argument(
|
||||||
|
'-b', '--build-dir',
|
||||||
|
metavar='BUILD_DIR',
|
||||||
|
help='Relativ or absolute path to output directory for processed packages and classes',
|
||||||
|
type=pathlib.Path,
|
||||||
|
nargs='?',
|
||||||
|
default='./build',
|
||||||
|
dest='build_dir'
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'-r', '--recursive',
|
||||||
|
help='Recursively search subdirectories for files. Default: false',
|
||||||
|
action='store_true',
|
||||||
|
dest='recursive'
|
||||||
|
)
|
||||||
|
input_group.add_argument(
|
||||||
|
'-i', '--input-file',
|
||||||
|
metavar='FILE',
|
||||||
|
help='Filename to be built. Can be in valid .pysty or .pycls format',
|
||||||
|
type=pathlib.Path,
|
||||||
|
dest='input_file'
|
||||||
|
)
|
||||||
|
output_group.add_argument(
|
||||||
|
'-n', '--name',
|
||||||
|
help='Name of the package / class to be formatted.',
|
||||||
|
type=str,
|
||||||
|
choices=[FILENAME_TYPE_RAW_NAME, FILENAME_TYPE_PREPEND_AUTHOR],
|
||||||
|
default=FILENAME_TYPE_PREPEND_AUTHOR,
|
||||||
|
dest='latex_name'
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'-g', '--git-version',
|
||||||
|
help='Insert git version information into build. This assumes your input'
|
||||||
|
'files are located in a git repository. Default: false',
|
||||||
|
action='store_true',
|
||||||
|
dest='use_git'
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'-d', '--allow-dirty',
|
||||||
|
help='If git flag is set, allow building of a dirty repo. Default: false',
|
||||||
|
action='store_true',
|
||||||
|
dest='allow_dirty'
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'-p',
|
||||||
|
'--pytex-version',
|
||||||
|
help='Write PyTeX version information into built LaTeX files',
|
||||||
|
action='store_true',
|
||||||
|
dest='include_pytex_version'
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'-t', '--build-time',
|
||||||
|
help='Insert build time into built LaTeX files',
|
||||||
|
action='store_true',
|
||||||
|
dest='include_timestamp'
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'-l', '--license',
|
||||||
|
help='Insert MIT license into package header',
|
||||||
|
action='store_true',
|
||||||
|
dest='include_license'
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'-a', '--author',
|
||||||
|
help='Set author of packages',
|
||||||
|
type=str,
|
||||||
|
dest='author'
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'-f', '--force',
|
||||||
|
help='Overwrite unknown existing files without confirmation',
|
||||||
|
action='store_true',
|
||||||
|
dest='overwrite_existing_files'
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
build(**vars(args))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
check_existence = True
|
main()
|
||||||
if len(sys.argv) == 2:
|
|
||||||
if sys.argv[1] == '--only-new':
|
|
||||||
check_existence = False
|
|
||||||
build(
|
|
||||||
src_dir=Path('./src').resolve(),
|
|
||||||
build_dir=Path('./build').resolve(),
|
|
||||||
check_existence=check_existence
|
|
||||||
)
|
|
||||||
|
|
|
@ -1,69 +1,99 @@
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import git
|
import git
|
||||||
|
from typing import Optional, Union, List
|
||||||
|
|
||||||
import PyTeX
|
import PyTeX
|
||||||
|
|
||||||
from build_scripts.git_hook import get_latest_commit, is_recent
|
from build_scripts.git_hook import get_latest_commit, is_recent
|
||||||
|
|
||||||
from .build_information import build_information
|
from .build_information import build_information, BuildInfo
|
||||||
|
|
||||||
|
|
||||||
def build(src_dir: Path, build_dir: Path, check_existence: bool = True):
|
def pytex_msg(msg: str):
|
||||||
print('[PyTeX] Getting git repository information...')
|
print('[PyTeX] ' + msg)
|
||||||
extra_header, repo_description = build_information()
|
|
||||||
print('[PyTeX] Building version {version} of LatexPackages'.format(version=repo_description))
|
|
||||||
print('[PyTeX] Latest commit message: ' + get_latest_commit(git.Repo()).message.strip())
|
|
||||||
if git.Repo().is_dirty(untracked_files=True):
|
|
||||||
extra_header += ['WARNING: Local changes to git repository detected.',
|
|
||||||
' The build will not be reproducible (!)']
|
|
||||||
num_packages = 0
|
|
||||||
num_skipped_packages = 0
|
|
||||||
num_classes = 0
|
|
||||||
num_skipped_classes = 0
|
|
||||||
|
|
||||||
for file in src_dir.rglob('*.pysty'):
|
|
||||||
output_dir = build_dir / str(file.parent.relative_to(src_dir))
|
|
||||||
if not is_recent(file, git.Repo()):
|
|
||||||
if not check_existence:
|
|
||||||
print('[PyTex] Skipping file {file} since it was not modified since last build'.format(file=file.name))
|
|
||||||
num_skipped_packages += 1
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
if (output_dir / ('mkessler-' + str(file.with_suffix('.sty').name))).exists():
|
|
||||||
print('[PyTex] Skipping file {file} since it was not modified since '
|
|
||||||
'last build and already exists'.format(file=file.name))
|
|
||||||
num_skipped_packages += 1
|
|
||||||
continue
|
|
||||||
|
|
||||||
num_packages += 1
|
class TexFileToFormat:
|
||||||
|
def __init__(self, src_path: Path, build_dir: Path):
|
||||||
|
self.src_path = src_path
|
||||||
|
self.build_path = build_dir
|
||||||
|
|
||||||
|
def format(self):
|
||||||
|
if '.pysty' in self.src_path.name:
|
||||||
formatter = PyTeX.PackageFormatter(
|
formatter = PyTeX.PackageFormatter(
|
||||||
package_name=file.with_suffix('').name,
|
package_name=self.src_path.with_suffix('').name,
|
||||||
extra_header=extra_header)
|
extra_header=[]) # TODO: extra header
|
||||||
print('[PyTeX] Writing file {}'.format(formatter.file_name))
|
|
||||||
formatter.make_default_macros()
|
|
||||||
formatter.format_file(file, output_dir)
|
|
||||||
for file in src_dir.rglob('*.pycls'):
|
|
||||||
output_dir = build_dir / str(file.parent.relative_to(src_dir))
|
|
||||||
if not is_recent(file, git.Repo()):
|
|
||||||
if not check_existence:
|
|
||||||
print('[PyTex] Skipping file {file} since it was not modified since last build'.format(file=file.name))
|
|
||||||
num_skipped_classes += 1
|
|
||||||
continue
|
|
||||||
else:
|
else:
|
||||||
if (output_dir / ('mkessler-' + str(file.with_suffix('.cls').name))).exists():
|
|
||||||
print('[PyTex] Skipping file {file} since it was not modified since '
|
|
||||||
'last build and already exists'.format(file=file.name))
|
|
||||||
num_skipped_classes += 1
|
|
||||||
continue
|
|
||||||
output_dir = build_dir / str(file.parent.relative_to(src_dir))
|
|
||||||
num_classes += 1
|
|
||||||
formatter = PyTeX.ClassFormatter(
|
formatter = PyTeX.ClassFormatter(
|
||||||
class_name=file.with_suffix('').name,
|
class_name=self.src_path.with_suffix('').name,
|
||||||
extra_header=extra_header)
|
extra_header=[]) # TODO
|
||||||
print('[PyTeX] Writing class file {}'.format(formatter.file_name))
|
pytex_msg('Writing file {}'.format(formatter.file_name))
|
||||||
formatter.make_default_macros()
|
formatter.make_default_macros()
|
||||||
formatter.format_file(input_path=file, output_dir=output_dir)
|
formatter.format_file(self.src_path, self.build_path)
|
||||||
build_info = {
|
|
||||||
|
|
||||||
|
def build(
|
||||||
|
src_dir: Optional[Path] = None,
|
||||||
|
build_dir: Optional[Path] = None,
|
||||||
|
input_file: Optional[Path] = None,
|
||||||
|
author: Optional[str] = None,
|
||||||
|
latex_name: str = 'prepend-author', # name handling
|
||||||
|
recursive: bool = False, # input control
|
||||||
|
include_timestamp: bool = False, # header
|
||||||
|
include_pytex_version: bool = False, # header
|
||||||
|
include_license: bool = False, # header
|
||||||
|
include_git_version: bool = False, # header
|
||||||
|
include_pytex_info_text: bool = False, # header
|
||||||
|
use_git: bool = False, # versioning
|
||||||
|
allow_dirty: bool = False, # versioning
|
||||||
|
overwrite_existing_files: bool = False, # output control
|
||||||
|
build_all: bool = False, # output control / versioning
|
||||||
|
write_build_information: bool = True, # meta
|
||||||
|
):
|
||||||
|
pytex_msg('Getting git repository information...')
|
||||||
|
current_build_info = BuildInfo(
|
||||||
|
include_timestamp=include_timestamp,
|
||||||
|
include_pytex_version=include_pytex_version,
|
||||||
|
include_license=include_license,
|
||||||
|
include_git_version=include_git_version,
|
||||||
|
include_pytex_info_text=include_pytex_info_text,
|
||||||
|
author=author,
|
||||||
|
pytex_repo=None, # TODO
|
||||||
|
packages_repo=None # TODO
|
||||||
|
)
|
||||||
|
old_build_info = {} # TODO: read this in from file
|
||||||
|
# extra_header += ['WARNING: Local changes to git repository detected.',
|
||||||
|
# ' The build will not be reproducible (!)']
|
||||||
|
|
||||||
|
files = []
|
||||||
|
if input_file:
|
||||||
|
files.append(input_file)
|
||||||
|
if src_dir:
|
||||||
|
if recursive:
|
||||||
|
for file in src_dir.rglob('*.pysty'):
|
||||||
|
files.append(file)
|
||||||
|
for file in src_dir.rglob('*.pycls'):
|
||||||
|
files.append(file)
|
||||||
|
else:
|
||||||
|
for file in src_dir.glob('*.pysty'):
|
||||||
|
files.append(file)
|
||||||
|
for file in src_dir.glob('*.pycls'):
|
||||||
|
files.append(file)
|
||||||
|
|
||||||
|
input_dir = src_dir if src_dir else input_file.parent
|
||||||
|
output_dir = build_dir if build_dir else input_file.parent
|
||||||
|
sources_to_build = []
|
||||||
|
for file in files:
|
||||||
|
sources_to_build.append(
|
||||||
|
TexFileToFormat(
|
||||||
|
src_path=file,
|
||||||
|
build_dir=output_dir / file.parent.relative_to(input_dir)
|
||||||
|
))
|
||||||
|
|
||||||
|
for source in sources_to_build:
|
||||||
|
source.format()
|
||||||
|
|
||||||
|
current_build_info = {
|
||||||
'build_time': '',
|
'build_time': '',
|
||||||
'packages': {
|
'packages': {
|
||||||
'built': '',
|
'built': '',
|
||||||
|
@ -86,5 +116,4 @@ def build(src_dir: Path, build_dir: Path, check_existence: bool = True):
|
||||||
'dirty': ''
|
'dirty': ''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
print(f'[PyTeX] Successfully built {num_packages} packages (skipped {num_skipped_packages}) '
|
pytex_msg('Build done')
|
||||||
f'and {num_classes} classes (skipped {num_skipped_classes}) in {build_dir}/')
|
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import git
|
import git
|
||||||
import datetime
|
import datetime
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
from build_scripts.git_hook import git_describe, get_latest_commit
|
from build_scripts.git_hook import git_describe, get_latest_commit
|
||||||
|
|
||||||
from .config import BUILD_DETAILS
|
from .config import BUILD_DETAILS, DATE_FORMAT
|
||||||
|
|
||||||
|
|
||||||
def build_information():
|
def build_information():
|
||||||
|
@ -18,3 +19,58 @@ def build_information():
|
||||||
packages_version=repo_description,
|
packages_version=repo_description,
|
||||||
packages_commit_hash=get_latest_commit(repo).hexsha[0:7]
|
packages_commit_hash=get_latest_commit(repo).hexsha[0:7]
|
||||||
), BUILD_DETAILS)), repo_description
|
), BUILD_DETAILS)), repo_description
|
||||||
|
|
||||||
|
|
||||||
|
class BuildInfo:
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
include_timestamp: bool = False,
|
||||||
|
include_pytex_version: bool = False,
|
||||||
|
include_license: bool = False,
|
||||||
|
include_git_version: bool = False,
|
||||||
|
include_pytex_info_text: bool = False,
|
||||||
|
author: Optional[str] = None,
|
||||||
|
pytex_repo: Optional[git.Repo] = None,
|
||||||
|
packages_repo: Optional[git.Repo] = None):
|
||||||
|
self.author = author
|
||||||
|
|
||||||
|
self._pytex_repo = pytex_repo
|
||||||
|
self._packages_repo = packages_repo
|
||||||
|
self._pytex_repo_commit = None
|
||||||
|
self._packages_repo_commit = None
|
||||||
|
self._pytex_repo_version = None
|
||||||
|
self._packages_repo_version = None
|
||||||
|
|
||||||
|
self._header = None
|
||||||
|
|
||||||
|
self.get_repo_commits()
|
||||||
|
self.get_repo_version()
|
||||||
|
|
||||||
|
self.create_header(
|
||||||
|
include_timestamp=include_timestamp,
|
||||||
|
include_pytex_version=include_pytex_version,
|
||||||
|
include_license=include_license,
|
||||||
|
include_git_version=include_git_version,
|
||||||
|
include_pytex_info_text=include_pytex_info_text
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_repo_commits(self):
|
||||||
|
if self._packages_repo:
|
||||||
|
self._packages_repo_commit = get_latest_commit(self._packages_repo)
|
||||||
|
if self._pytex_repo:
|
||||||
|
self._pytex_repo_commit = get_latest_commit(self._pytex_repo)
|
||||||
|
|
||||||
|
def get_repo_version(self):
|
||||||
|
if self._packages_repo_commit:
|
||||||
|
self._packages_repo_version = git_describe(self._packages_repo_commit)
|
||||||
|
if self._pytex_repo_commit:
|
||||||
|
self._pytex_repo_version = git_describe(self._pytex_repo_commit)
|
||||||
|
|
||||||
|
def create_header(
|
||||||
|
self,
|
||||||
|
include_timestamp: bool = False,
|
||||||
|
include_pytex_version: bool = False,
|
||||||
|
include_license: bool = False,
|
||||||
|
include_git_version: bool = False,
|
||||||
|
include_pytex_info_text: bool = False):
|
||||||
|
pass
|
||||||
|
|
|
@ -4,3 +4,7 @@ BUILD_DETAILS = [
|
||||||
" PyTeX version: {pytex_version} (commit {pytex_commit_hash})",
|
" PyTeX version: {pytex_version} (commit {pytex_commit_hash})",
|
||||||
" LatexPackages version: {packages_version} (commit {packages_commit_hash})"
|
" LatexPackages version: {packages_version} (commit {packages_commit_hash})"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
FILENAME_TYPE_PREPEND_AUTHOR = 'prepend-author'
|
||||||
|
FILENAME_TYPE_RAW_NAME = 'raw'
|
||||||
|
DATE_FORMAT = '%Y/%m/%d %H:%M'
|
||||||
|
|
|
@ -1,14 +1,30 @@
|
||||||
|
import git
|
||||||
|
|
||||||
from .git_version import get_latest_commit
|
from .git_version import get_latest_commit
|
||||||
|
from typing import Union, Optional, List
|
||||||
|
|
||||||
|
|
||||||
def is_recent(file, repo):
|
def is_recent(file, repo, compare: Optional[Union[git.Commit, List[git.Commit]]] = None) -> Optional[bool]:
|
||||||
modified_files = [item.a_path for item in repo.index.diff(None)]
|
modified_files = [item.a_path for item in repo.index.diff(None)]
|
||||||
if file in modified_files:
|
if file in modified_files:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
newly_committed_files = []
|
||||||
|
if type(compare) == git.Commit:
|
||||||
|
newly_committed_files = [item.a_path for item in repo.index.diff(compare)]
|
||||||
|
elif type(compare) == list:
|
||||||
|
for commit in compare:
|
||||||
|
for item in repo.index.diff(commit):
|
||||||
|
newly_committed_files.append(item.a_path)
|
||||||
|
elif type is None:
|
||||||
for parent in get_latest_commit(repo).parents:
|
for parent in get_latest_commit(repo).parents:
|
||||||
newly_committed_files = [item.a_path for item in repo.index.diff(parent)]
|
for item in repo.index.diff(parent):
|
||||||
|
newly_committed_files.append(item.a_path)
|
||||||
|
else:
|
||||||
|
print("Invalid argument type for compare")
|
||||||
|
return None
|
||||||
|
|
||||||
if file in newly_committed_files:
|
if file in newly_committed_files:
|
||||||
return True
|
return True
|
||||||
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
0
build_scripts/utils/__init__.py
Normal file
0
build_scripts/utils/__init__.py
Normal file
Loading…
Reference in a new issue