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
|
||||
from pathlib import Path
|
||||
#! /usr/bin/python3
|
||||
import argparse
|
||||
import pathlib
|
||||
|
||||
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__":
|
||||
check_existence = True
|
||||
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
|
||||
)
|
||||
main()
|
||||
|
|
|
@ -1,69 +1,99 @@
|
|||
from pathlib import Path
|
||||
import git
|
||||
from typing import Optional, Union, List
|
||||
|
||||
import PyTeX
|
||||
|
||||
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):
|
||||
print('[PyTeX] Getting git repository information...')
|
||||
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
|
||||
def pytex_msg(msg: str):
|
||||
print('[PyTeX] ' + msg)
|
||||
|
||||
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
|
||||
formatter = PyTeX.PackageFormatter(
|
||||
package_name=file.with_suffix('').name,
|
||||
extra_header=extra_header)
|
||||
print('[PyTeX] Writing file {}'.format(formatter.file_name))
|
||||
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(
|
||||
package_name=self.src_path.with_suffix('').name,
|
||||
extra_header=[]) # TODO: extra header
|
||||
else:
|
||||
formatter = PyTeX.ClassFormatter(
|
||||
class_name=self.src_path.with_suffix('').name,
|
||||
extra_header=[]) # TODO
|
||||
pytex_msg('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:
|
||||
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(
|
||||
class_name=file.with_suffix('').name,
|
||||
extra_header=extra_header)
|
||||
print('[PyTeX] Writing class file {}'.format(formatter.file_name))
|
||||
formatter.make_default_macros()
|
||||
formatter.format_file(input_path=file, output_dir=output_dir)
|
||||
build_info = {
|
||||
formatter.format_file(self.src_path, self.build_path)
|
||||
|
||||
|
||||
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': '',
|
||||
'packages': {
|
||||
'built': '',
|
||||
|
@ -86,5 +116,4 @@ def build(src_dir: Path, build_dir: Path, check_existence: bool = True):
|
|||
'dirty': ''
|
||||
}
|
||||
}
|
||||
print(f'[PyTeX] Successfully built {num_packages} packages (skipped {num_skipped_packages}) '
|
||||
f'and {num_classes} classes (skipped {num_skipped_classes}) in {build_dir}/')
|
||||
pytex_msg('Build done')
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import git
|
||||
import datetime
|
||||
from typing import Optional
|
||||
|
||||
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():
|
||||
|
@ -18,3 +19,58 @@ def build_information():
|
|||
packages_version=repo_description,
|
||||
packages_commit_hash=get_latest_commit(repo).hexsha[0:7]
|
||||
), 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})",
|
||||
" 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 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)]
|
||||
if file in modified_files:
|
||||
return True
|
||||
|
||||
for parent in get_latest_commit(repo).parents:
|
||||
newly_committed_files = [item.a_path for item in repo.index.diff(parent)]
|
||||
if file in newly_committed_files:
|
||||
return True
|
||||
return False
|
||||
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 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:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
|
0
build_scripts/utils/__init__.py
Normal file
0
build_scripts/utils/__init__.py
Normal file
Loading…
Reference in a new issue