Source code for flash.flmake.merge
import os
import shutil
import json
# relative imports needed!
from . import logger
from .run import init_rundir
from .setup_globals import gvars
from .utils import desc_cmd_metadata
USAGE = ("Merges a run directory with all previous\n"
"runs in its history. If a target directory\n"
"is provided, will perform merge in this dir.\n"
"Does nothing if a top-level run (no history).\n"
"Merges get new ids and empty histories.\n\n"
"usage: flmake merge <leaf-dir|id> [<target-dir>]")
[docs]def main(opts, rc, msg):
"""Merges run with its history."""
init_rundir()
# get run dirs that
subdirs = [f for f in os.listdir('.') if os.path.isdir(f)]
rundirs = [d for d in subdirs if os.path.exists(os.path.join(d, gvars.desc_filename))]
# grab the hashes, diriectory names, and descriptions
id_dir = {}
id_desc = {}
for rundir in rundirs:
with open(os.path.join(rundir, gvars.desc_filename)) as desc_file:
desc = json.load(desc_file)
if 'run' not in desc:
continue
id_dir[desc['run']['id']] = rundir
id_desc[desc['run']['id']] = desc
# Get leaf id and dir
leaf_id = opts[0] if opts[0] in id_dir else \
[id for id, d in id_dir.items() if os.path.samefile(opts[0], d)][0]
leaf_dir = id_dir[leaf_id]
# Get target dir
target_id = gvars.run_id
target_dir = opts[1] if 1 < len(opts) else gvars.run_dir
if os.path.exists(target_dir):
raise SystemExit("target directory {0} already exists.".format(target_dir))
os.mkdir(target_dir)
# Copy over leaf files to target dir
try:
for f in sorted(os.listdir(leaf_dir)):
src = os.path.join(leaf_dir, f)
dst = os.path.join(target_dir, f)
print "{0} -> {1}".format(src, dst)
shutil.copy2(src, dst)
except shutil.Error as e:
shutil.rmtree(target_dir)
raise e
# Get history ids from leaf
with open(os.path.join(leaf_dir, gvars.desc_filename)) as leaf_desc_file:
leaf_desc = json.load(leaf_desc_file)
history = leaf_desc['run']['history'] + [leaf_desc['run']['id']]
# Copy over metadata from all previous runs in history
metafiles = set([gvars.desc_filename, 'flash.par'])
rename = lambda i, f: '.'.join([f.rpartition('.')[0], i, f.rpartition('.')[2]])
srcdst = [(os.path.join(id_dir[id], mf), os.path.join(target_dir, rename(id, mf))) \
for id in history for mf in metafiles]
for src, dst in srcdst:
print "{0} -> {1}".format(src, dst)
shutil.copy2(src, dst)
# Open previous description
with open(os.path.join(target_dir, gvars.desc_filename)) as desc_file:
desc = json.load(desc_file)
# write new flash description
prev_desc_run = desc['run']
desc['run'] = desc_cmd_metadata()
desc_run = desc['run']
desc_run['id'] = gvars.run_id
desc_run['history'] = []
if 'merge' not in desc:
desc['merge'] = {}
if 'history' not in desc['merge']:
desc['merge']['history'] = []
desc['merge']['history'] += history
with open(os.path.join(target_dir, gvars.desc_filename), 'w') as f:
json.dump(desc, f, indent=2)
# log this merge
if msg is None:
msg = "merged {0} into {1} ({2})".format(", ".join(history), target_id, target_dir)
logger.info(msg, "merge", target_id, target_dir)