Implemented simple 'bat pack' CLI command

No path rewriting yet, just simply copying the dependencies. They are
copied to the target directory + the path relative to the current working
directory. For example:

bat pack scenes/05-barber/05_02_C-agent_focused/05_02_C.lighting.blend /tmp/packer

will write to
/tmp/packer/scenes/05-barber/05_02_C-agent_focused/05_02_C.lighting.blend
and will copy ./path/to/file → /tmp/packer/path/to/file
This commit is contained in:
Sybren A. Stüvel 2018-03-02 17:59:04 +01:00
parent f2694df602
commit 5c8e074c68
4 changed files with 66 additions and 10 deletions

View File

@ -1,4 +1,5 @@
"""Common functionality for CLI parsers.""" """Common functionality for CLI parsers."""
import pathlib
def add_flag(argparser, flag_name: str, **kwargs): def add_flag(argparser, flag_name: str, **kwargs):
@ -14,3 +15,9 @@ def add_flag(argparser, flag_name: str, **kwargs):
**kwargs) **kwargs)
def shorten(cwd: pathlib.Path, somepath: pathlib.Path) -> pathlib.Path:
"""Return 'somepath' relative to CWD if possible."""
try:
return somepath.relative_to(cwd)
except ValueError:
return somepath

View File

@ -1,4 +1,5 @@
"""List dependencies of a blend file.""" """List dependencies of a blend file."""
import functools
import json import json
import logging import logging
import pathlib import pathlib
@ -34,14 +35,7 @@ def cli_list(args):
def report_text(bpath): def report_text(bpath):
reported_assets = set() reported_assets = set()
last_reported_bfile = None last_reported_bfile = None
cwd = pathlib.Path.cwd() shorten = functools.partial(common.shorten, pathlib.Path.cwd())
def shorten(somepath: pathlib.Path) -> pathlib.Path:
"""Return 'somepath' relative to CWD if possible."""
try:
return somepath.relative_to(cwd)
except ValueError:
return somepath
for usage in tracer.deps(bpath): for usage in tracer.deps(bpath):
filepath = usage.block.bfile.filepath.absolute() filepath = usage.block.bfile.filepath.absolute()

View File

@ -1,4 +1,13 @@
"""Create a BAT-pack for the given blend file.""" """Create a BAT-pack for the given blend file."""
import functools
import logging
import pathlib
import shutil
from blender_asset_tracer import tracer
from . import common
log = logging.getLogger(__name__)
def add_parser(subparsers): def add_parser(subparsers):
@ -6,7 +15,47 @@ def add_parser(subparsers):
parser = subparsers.add_parser('pack', help=__doc__) parser = subparsers.add_parser('pack', help=__doc__)
parser.set_defaults(func=cli_pack) parser.set_defaults(func=cli_pack)
parser.add_argument('blendfile', type=pathlib.Path)
parser.add_argument('target', type=pathlib.Path)
def cli_pack(args): def cli_pack(args):
raise NotImplementedError('bat pack not implemented yet') bpath = args.blendfile
if not bpath.exists():
log.fatal('File %s does not exist', args.bpath)
return 3
tpath = args.target
if tpath.exists() and not tpath.is_dir():
log.fatal('Target %s exists and is not a directory', tpath)
return 4
shorten = functools.partial(common.shorten, pathlib.Path.cwd())
already_copied = set()
for usage in tracer.deps(bpath):
if usage.asset_path.is_absolute():
raise NotImplementedError('Sorry, cannot handle absolute paths yet: %s' % usage)
for assetpath in usage.files():
try:
assetpath = assetpath.resolve()
except FileNotFoundError:
log.error('Dependency %s does not exist', assetpath)
if assetpath in already_copied:
log.debug('Already copied %s', assetpath)
continue
already_copied.add(assetpath)
relpath = shorten(assetpath)
if relpath.is_absolute():
raise NotImplementedError('Sorry, cannot handle absolute paths yet: %s in %s'
% (usage, assetpath))
full_target = tpath / relpath
full_target.parent.mkdir(parents=True, exist_ok=True)
# TODO(Sybren): when we target Py 3.6+, remove the str() calls.
print(relpath)
shutil.copyfile(str(assetpath), str(full_target))
log.info('Copied %d files to %s', len(already_copied), tpath)

View File

@ -35,7 +35,7 @@ class _BlockIterator:
limit_to: typing.Set[blendfile.BlendFileBlock] = frozenset(), limit_to: typing.Set[blendfile.BlendFileBlock] = frozenset(),
) -> typing.Iterator[blendfile.BlendFileBlock]: ) -> typing.Iterator[blendfile.BlendFileBlock]:
"""Expand blocks with dependencies from other libraries.""" """Expand blocks with dependencies from other libraries."""
bpath = bfile.filepath bpath = bfile.filepath.absolute().resolve()
root_dir = bpathlib.BlendPath(bpath.parent) root_dir = bpathlib.BlendPath(bpath.parent)
# Mapping from library path to data blocks to expand. # Mapping from library path to data blocks to expand.
@ -79,6 +79,12 @@ class _BlockIterator:
# and iterate over the blocks referred there. # and iterate over the blocks referred there.
for lib_bpath, idblocks in blocks_per_lib.items(): for lib_bpath, idblocks in blocks_per_lib.items():
lib_path = lib_bpath.to_path() lib_path = lib_bpath.to_path()
try:
lib_path = lib_path.resolve()
except FileNotFoundError:
log.warning('Library %s does not exist', lib_path)
continue
log.debug('Expanding %d blocks in %s', len(idblocks), lib_path) log.debug('Expanding %d blocks in %s', len(idblocks), lib_path)
with blendfile.BlendFile(lib_path) as libfile: with blendfile.BlendFile(lib_path) as libfile: