Repository: common-workflow-language/cwltool

Issue:
Crash with caret in secondaryFiles when there's no extension to remove
## Expected Behavior

> If string begins with one or more caret ^ characters, for each caret, remove the last file extension from the path (the last period . and all following characters). If there are no file extensions, the path is unchanged.

If the primary file has no extension, or its extension has been removed by previous caret(s), then extra carets in secondaryFiles should have no effect.

## Actual Behavior

If there are more carets in an entry of secondaryFiles than there are extensions in the primary file's path, cwltool crashes.

## Workflow Code

```yaml
cwlVersion: v1.0
class: CommandLineTool
baseCommand: echo
inputs:
  args:
    type: File
    inputBinding:
      position: 1
    secondaryFiles:
    - ^.abc
outputs: []
```

job:

```yaml
args:
  class: File
  path: foo
```

## Full Traceback

```pytb
/Users/jh36/venv/bin/cwltool 1.0.20180711112827
Resolved 'tool.cwl' to 'file:///Users/jh36/tool.cwl'
Got workflow error
Traceback (most recent call last):
  File "/Users/jh36/venv/lib/python3.6/site-packages/cwltool/executors.py", line 141, in run_jobs
    for job in jobiter:
  File "/Users/jh36/venv/lib/python3.6/site-packages/cwltool/command_line_tool.py", line 373, in job
    builder = self._init_job(job_order, runtimeContext)
  File "/Users/jh36/venv/lib/python3.6/site-packages/cwltool/process.py", line 654, in _init_job
    discover_secondaryFiles=getdefault(runtimeContext.toplevel, False)))
  File "/Users/jh36/venv/lib/python3.6/site-packages/cwltool/builder.py", line 260, in bind_input
    bindings.extend(self.bind_input(f, datum[f["name"]], lead_pos=lead_pos, tail_pos=f["name"], discover_secondaryFiles=discover_secondaryFiles))
  File "/Users/jh36/venv/lib/python3.6/site-packages/cwltool/builder.py", line 294, in bind_input
    sfpath = substitute(datum["basename"], sf)
  File "/Users/jh36/venv/lib/python3.6/site-packages/cwltool/builder.py", line 32, in substitute
    return substitute(value[0:value.rindex('.')], replace[1:])
ValueError: substring not found
Workflow error:
substring not found
Traceback (most recent call last):
  File "/Users/jh36/venv/lib/python3.6/site-packages/cwltool/executors.py", line 141, in run_jobs
    for job in jobiter:
  File "/Users/jh36/venv/lib/python3.6/site-packages/cwltool/command_line_tool.py", line 373, in job
    builder = self._init_job(job_order, runtimeContext)
  File "/Users/jh36/venv/lib/python3.6/site-packages/cwltool/process.py", line 654, in _init_job
    discover_secondaryFiles=getdefault(runtimeContext.toplevel, False)))
  File "/Users/jh36/venv/lib/python3.6/site-packages/cwltool/builder.py", line 260, in bind_input
    bindings.extend(self.bind_input(f, datum[f["name"]], lead_pos=lead_pos, tail_pos=f["name"], discover_secondaryFiles=discover_secondaryFiles))
  File "/Users/jh36/venv/lib/python3.6/site-packages/cwltool/builder.py", line 294, in bind_input
    sfpath = substitute(datum["basename"], sf)
  File "/Users/jh36/venv/lib/python3.6/site-packages/cwltool/builder.py", line 32, in substitute
    return substitute(value[0:value.rindex('.')], replace[1:])
ValueError: substring not found

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/jh36/venv/lib/python3.6/site-packages/cwltool/main.py", line 605, in main
    logger=_logger)
  File "/Users/jh36/venv/lib/python3.6/site-packages/cwltool/executors.py", line 39, in __call__
    return self.execute(*args, **kwargs)
  File "/Users/jh36/venv/lib/python3.6/site-packages/cwltool/executors.py", line 89, in execute
    self.run_jobs(process, job_order_object, logger, runtime_context)
  File "/Users/jh36/venv/lib/python3.6/site-packages/cwltool/executors.py", line 170, in run_jobs
    raise WorkflowException(Text(e))
cwltool.errors.WorkflowException: substring not found
```

## Your Environment

* cwltool version: 1.0.20180711112827


Discussion:

Resolving patch:
diff --git a/cwltool/builder.py b/cwltool/builder.py
--- a/cwltool/builder.py
+++ b/cwltool/builder.py
@@ -50,8 +50,12 @@ def content_limit_respected_read(f):  # type: (IO) -> Text
 
 
 def substitute(value, replace):  # type: (Text, Text) -> Text
-    if replace[0] == "^":
-        return substitute(value[0:value.rindex('.')], replace[1:])
+    if replace.startswith("^"):
+        try:
+            return substitute(value[0:value.rindex('.')], replace[1:])
+        except ValueError:
+            # No extension to remove
+            return value + replace.lstrip("^")
     return value + replace
 
 def formatSubclassOf(fmt, cls, ontology, visited):


Test patch: