Repository: ocr-d/core
Issue: Line detection via ocrd: PAGE XML is overwritten, result is empty

Using
```shell
ocrd process -m ocrd-assets/dist/mets.xml characterize/exif segment-region/tesserocr
```
works great (i.e.  metadata and regions show up in OUTPUT PAGE XML).
However, adding line detection
```shell
ocrd process -m ocrd-assets/dist/mets.xml characterize/exif segment-region/tesserocr segment-line/tesserocr
```
results in “empty” XML:
```xml
<PcGts xmlns="http://schema.primaresearch.org/PAGE/gts/pagecontent/2017-07-15" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schema.primaresearch.org/PAGE/gts/pagecontent/2017-07-15 http://schema.primaresearch.org/PAGE/gts/pagecontent/2017-07-15/pagecontent.xsd">
        <Page imageFileName="http://localhost:5001/00000005.tif">
        </Page>
</PcGts>
```


Changed files:
ocrd/cli/process.py, ocrd/decorators.py, ocrd/processor/base.py

diff --git a/ocrd/cli/process.py b/ocrd/cli/process.py
index 33e5efcd..c8087928 100644
--- a/ocrd/cli/process.py
+++ b/ocrd/cli/process.py
@@ -12,28 +12,56 @@ from ocrd.decorators import ocrd_cli_options
 
 @click.command('process')
 @ocrd_cli_options
-@click.option('-T', '--ocrd-tool', multiple=True)
+@click.option('-T', '--ocrd-tool', multiple=True, type=click.Path(exists=True, dir_okay=False), help='register all executables from a ocrd-tool.json file')
 @click.argument('steps', nargs=-1)
-def process_cli(mets_url, **kwargs):
+def process_cli(mets, steps, **kwargs):
     """
-    Execute OCR-D processors for a METS file directly.
+    Execute OCR-D processor executables for a METS file.
+
+    Run each of the STEPS executables one after another.
+
+    Order of comma-separated values for -I, -O, -p corresponds to order of steps.
     """
     resolver = Resolver()
-    workspace = resolver.workspace_from_url(mets_url)
+    workspace = resolver.workspace_from_url(mets)
 
     cmds = []
     for ocrd_tool_file in kwargs['ocrd_tool']:
         with codecs.open(ocrd_tool_file, encoding='utf-8') as f:
             obj = json.loads(f.read())
-            for tool in obj['tools']:
-                cmds.append(tool['binary'])
+            for tool in obj['tools'].values():
+                cmds.append(tool['executable'])
 
-    for cmd in kwargs['steps']:
+    for cmd in steps:
         if cmd not in cmds:
             raise Exception("Tool not registered: '%s'" % cmd)
 
-    for cmd in kwargs['steps']:
-        run_cli(cmd, mets_url, resolver, workspace)
+    # fixme: this really should be coming from workflow engine (giving steps, i/o fileGrps, parameter files)
+    # fixme: using the command line here is inefficient
+    # fixme: someone should go and check if the first input_file_grp actually exists
+    if 'input_file_grp' not in kwargs:
+        raise Exception("Need input_file_grp USE(s)")
+    if 'output_file_grp' not in kwargs:
+        raise Exception("Need output_file_grp USE(s)")
+    if 'parameter' not in kwargs:
+        raise Exception("Need parameter file(s)")
+    input_file_grps = kwargs['input_file_grp'].split(',')
+    if len(input_file_grps) != len(steps):
+        raise Exception("Number of input_file_grp arguments (%d) does not match number of steps (%d)" % (len(input_file_grps), len(steps)))
+    output_file_grps = kwargs['output_file_grp'].split(',')
+    if len(output_file_grps) != len(steps):
+        raise Exception("Number of output_file_grp arguments (%d) does not match number of steps (%d)" % (len(output_file_grps), len(steps)))
+    parameters = kwargs['parameter'].split(',')
+    if len(parameters) != len(steps):
+        raise Exception("Number of parameter files (%d) does not match number of steps (%d)" % (len(parameters), len(steps)))
+
+    for cmd, input_file_grp, output_file_grp, parameter in zip(steps, input_file_grps, output_file_grps, parameters):
+        run_cli(cmd, mets, resolver, workspace,
+                log_level=kwargs['log_level'],
+                group_id=kwargs['group_id'],
+                input_file_grp=input_file_grp,
+                output_file_grp=output_file_grp,
+                parameter=parameter)
 
     workspace.reload_mets()
 
diff --git a/ocrd/decorators.py b/ocrd/decorators.py
index 5d7702f9..064a59dc 100644
--- a/ocrd/decorators.py
+++ b/ocrd/decorators.py
@@ -9,6 +9,7 @@ from ocrd.logging import setOverrideLogLevel
 
 def _set_root_logger_version(ctx, param, value):    # pylint: disable=unused-argument
     setOverrideLogLevel(value)
+    return value
 
 def ocrd_cli_wrap_processor(processorClass, ocrd_tool=None, mets=None, working_dir=None, dump_json=False, version=False, **kwargs):
     if dump_json:
diff --git a/ocrd/processor/base.py b/ocrd/processor/base.py
index 921c1ce7..52ea63d7 100644
--- a/ocrd/processor/base.py
+++ b/ocrd/processor/base.py
@@ -73,7 +73,6 @@ def run_processor(
     )
     workspace.save_mets()
 
-# TODO not used as of 0.8.2
 def run_cli(
         binary,
         mets_url=None,
@@ -90,12 +89,21 @@ def run_cli(
     Create a workspace for mets_url and run MP CLI through it
     """
     workspace = _get_workspace(workspace, resolver, mets_url, working_dir)
-    log.debug("Running binary '%s'", binary)
-    subprocess.call([
-        binary,
-        '--mets', mets_url,
-        '--working-dir', workspace.directory
-    ])
+    args = [binary, '--working-dir', workspace.directory]
+    if mets_url:
+        args += ['--mets', mets_url]
+    if log_level:
+        args += ['--log-level', log_level]
+    if group_id:
+        args += ['--group-id', group_id]
+    if input_file_grp:
+        args += ['--input-file-grp', input_file_grp]
+    if output_file_grp:
+        args += ['--output-file-grp', output_file_grp]
+    if parameter:
+        args += ['--parameter', parameter]
+    log.debug("Running subprocess '%s'", ' '.join(args))
+    subprocess.call(args)
 
 class Processor(object):
     """