@@ -15,6 +15,7 @@ import (
1515 "sort"
1616 "strings"
1717
18+ "github.com/atotto/clipboard"
1819 "github.com/dustin/go-humanize"
1920 "github.com/gdamore/tcell/v2"
2021 "github.com/pkg/profile"
@@ -326,6 +327,7 @@ func runInteractive(img *Image) error {
326327 tree := tview .NewTreeView ().
327328 SetRoot (root ).
328329 SetCurrentNode (root )
330+ navi := tview .NewTextView ()
329331
330332 for _ , layer := range img .Layers {
331333 text := strings .TrimPrefix (layer .CreatedBy , "/bin/sh -c " )
@@ -340,7 +342,8 @@ func runInteractive(img *Image) error {
340342 text = "RUN " + text
341343 }
342344 tn := tview .NewTreeNode (text )
343- addFiles (tn , layer .Files , true )
345+ tn .SetReference (layer )
346+ addFiles (tn , layer .Files , nil )
344347 root .AddChild (tn )
345348 }
346349
@@ -358,23 +361,61 @@ func runInteractive(img *Image) error {
358361 })
359362
360363 tree .SetInputCapture (func (e * tcell.EventKey ) * tcell.EventKey {
361- if e .Rune () == 'q' {
364+ switch e .Rune () {
365+ case 'q' :
362366 app .Stop ()
363- }
364- if e .Rune () == 'u' {
365- parent , ok := tree .GetCurrentNode ().GetReference ().(* tview.TreeNode )
366- if ok && parent != nil {
367- parent .SetExpanded (false )
368- tree .SetCurrentNode (parent )
367+ case 'u' :
368+ node , ok := tree .GetCurrentNode ().GetReference ().(* TreeNode )
369+ if ok && node .parent != nil {
370+ node .parent .value .SetExpanded (false )
371+ tree .SetCurrentNode (node .parent .value )
369372 }
373+ case 'y' :
374+ _ = clipboard .WriteAll (navi .GetText (true ))
370375 }
371376 return e
372377 })
373378
374- return app .SetRoot (tree , true ).Run ()
379+ tree .SetChangedFunc (func (target * tview.TreeNode ) {
380+ node , ok := target .GetReference ().(* TreeNode )
381+ if ok {
382+ navi .SetText (node .ExtractCommand ())
383+ } else {
384+ navi .SetText ("" )
385+ }
386+ })
387+ flex := tview .NewFlex ().
388+ SetDirection (tview .FlexRow ).
389+ AddItem (tree , 0 , 1 , true ).
390+ AddItem (navi , 1 , 0 , false )
391+ return app .SetRoot (flex , true ).SetFocus (flex ).Run ()
392+ }
393+
394+ type TreeNode struct {
395+ layerID string
396+ parent * TreeNode
397+ value * tview.TreeNode
398+ key string
399+ dir bool
400+ }
401+
402+ func (n * TreeNode ) Path () string {
403+ if n .parent == nil {
404+ return n .key
405+ }
406+ return n .parent .Path () + "/" + n .key
407+ }
408+
409+ func (n * TreeNode ) ExtractCommand () string {
410+ layerCmd := "tar xO " + n .layerID + "/layer.tar"
411+ if n .dir {
412+ return layerCmd + " | tar x " + n .Path ()
413+ } else {
414+ return layerCmd + " | tar xO " + n .Path ()
415+ }
375416}
376417
377- func addFiles (node * tview.TreeNode , files []* FileInfo , root bool ) int64 {
418+ func addFiles (node * tview.TreeNode , files []* FileInfo , parent * TreeNode ) int64 {
378419 tree := make (map [string ][]* FileInfo )
379420 size := int64 (0 )
380421 for _ , f := range files {
@@ -392,28 +433,39 @@ func addFiles(node *tview.TreeNode, files []*FileInfo, root bool) int64 {
392433 }
393434
394435 type entry struct {
395- node * tview. TreeNode
436+ node * TreeNode
396437 size int64
397438 }
398439 entries := make ([]* entry , 0 , len (tree ))
399440 for key := range tree {
400441 t := tview .NewTreeNode (key )
401- s := addFiles (t , tree [key ], false )
442+ child := & TreeNode {
443+ parent : parent ,
444+ value : t ,
445+ key : key ,
446+ }
447+ if parent != nil {
448+ child .layerID = parent .layerID
449+ } else {
450+ child .layerID = node .GetReference ().(* Layer ).ID
451+ }
452+ s := addFiles (t , tree [key ], child )
402453 entries = append (entries , & entry {
403- node : t ,
454+ node : child ,
404455 size : s ,
405456 })
406457 }
407458 sort .Slice (entries , func (i , j int ) bool {
408459 return entries [i ].size > entries [j ].size
409460 })
410461 for _ , e := range entries {
411- node .AddChild (e .node )
412- e .node .SetReference (node )
462+ node .AddChild (e .node . value )
463+ e .node .value . SetReference (e . node )
413464 }
414465 text := humanizeBytes (size ) + ": " + node .GetText ()
415- if ! root && len (entries ) > 0 {
466+ if parent != nil && len (entries ) > 0 {
416467 text += "/"
468+ parent .dir = true
417469 }
418470 node .SetText (text )
419471 node .SetExpanded (false )
0 commit comments