Improves the determination of the proper parent for exec and file ops.
With file ops, it will only consider inputs and ignore secondary inputs.
This prevents the following case:
```
FROM busybox AS build1
RUN echo foo > /hello
FROM scratch
COPY --from=build1 /hello .
```
Previously, `build1` would be considered the parent of the copy
instruction. Now, copy properly does not have a parent.
If there are multiple file ops and the operations disagree on the
canonical "parent", we give up on trying to find a canonical parent and
assume there is none.
For exec operations, whichever input is associated with the root mount
is considered the primary parent.
For all other operations, the first parent is considered the primary
parent if it exists.
Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
When the builder loads a dockerfile, it does it by using the base name
of the dockerfile path and only loads the innermost directory. This
means that the source name we're looking for is the base name and not
the full relative path.
Update the set breakpoints functionality so it takes this into account.
Fixes scenarios where DAP is used with a dockerfile nested in the
context.
Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
Invoking the shell will cause it to persist across the entire build and
to re-execute whenever the builder pauses at another location again.
This still requires using `exec` to launch the shell. Launching by frame
id is also removed since it no longer applies to this version.
Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
Add a file explorer to the debugger that allows exploring the filesystem
of the current container. It will show directory contents, file
contents, and symlink destinations. It will also show the file mode
associated with a file.
The file explorer defaults to marking itself as an expensive operation
so the debugger doesn't automatically retrieve the information.
Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
Change how breakpoints and stepping works. These now work more how you
would expect another programming language to work. Breakpoints happen
before the step has been invoked rather than after which means you can
inspect the state before the command runs.
This has the advantage of being more intuitive for someone familiar with
other debuggers. The negative is that you can't run to after a certain
step as easily as you could before. Instead, you would run to that stage
and then use next to go to the step directly afterwards.
Step in and out also now have different behaviors. When a step has
multiple inputs, the inputs of non-zero index are considered like
"function calls". The most common cause of this is to use `COPY --from`
or a bind mount. Stepping into these will cause it to jump to the
beginning of the call chain for that branch. Using step out will exit
back to the location where step in was used.
This change also makes it so some steps may be invoked multiple times in
the callgraph if multiple steps depend on them. The reused steps will
still be cached, but you may end up stepping through more lines than the
previous implementation.
Stack traces now represent where these step in and step out areas
happen rather than the previous steps. This can help you know from where
a certain step is being used.
Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
In the repl context, we will now return the error instead of directly
printing it. We also suppress reporting errors from cobra. The logic
flow has also been changed to prevent returning errors from cobra unless
there was something related to the command line invocation so usage will
only be printed when a command was typed wrong and it will not show up
for every error.
Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>