2026-10-11 01:06:21 +00:00
package ckconfig
2026-10-07 13:55:43 +00:00
import (
"bytes"
"errors"
"fmt"
2026-10-11 01:39:23 +00:00
"io"
2026-10-07 13:55:43 +00:00
"strconv"
"unicode"
2026-10-11 01:39:23 +00:00
commandkit "gitea.maximumdirect.net/eric/CommandKit"
)
2026-10-07 13:55:43 +00:00
type effectiveDocument struct {
name string
2026-10-11 01:39:23 +00:00
view View
2026-10-07 13:55:43 +00:00
}
2026-10-11 01:39:23 +00:00
func runConfigShow [ I , S any ] ( invocation commandkit . Invocation , plan * configOperationPlan [ I , S ] , state S ) commandkit . Outcome {
documents := make ( [ ] effectiveDocument , 0 , len ( plan . scopes ) )
diagnostics := make ( [ ] commandkit . Diagnostic , 0 )
for _ , selected := range plan . scopes {
2026-10-07 16:47:28 +00:00
if err := invocation . Context . Err ( ) ; err != nil {
2026-10-11 01:39:23 +00:00
return configOperationFailure ( err , diagnostics , false )
}
if selected . scope . scope . Acquire == nil {
return configOperationFailure ( fmt . Errorf ( "configuration scope %q has no acquisition callback" , selected . scope . scope . Name ) , diagnostics , false )
2026-10-07 16:47:28 +00:00
}
2026-10-11 01:39:23 +00:00
acquired , acquireErr := selected . scope . scope . Acquire ( invocation . Context , Request {
Operation : Show ,
Selection : plan . selection ,
} , selected . input , state )
2026-10-07 13:55:43 +00:00
diagnostics = append ( diagnostics , acquired . Diagnostics ... )
if acquireErr != nil {
2026-10-11 01:39:23 +00:00
return configOperationFailure ( acquireErr , diagnostics , false )
2026-10-07 13:55:43 +00:00
}
2026-10-07 16:47:28 +00:00
if err := invocation . Context . Err ( ) ; err != nil {
2026-10-11 01:39:23 +00:00
return configOperationFailure ( err , diagnostics , false )
2026-10-07 16:47:28 +00:00
}
2026-10-07 13:55:43 +00:00
if acquired . Value . Effective == nil {
2026-10-11 01:39:23 +00:00
return configOperationFailure ( fmt . Errorf ( "configuration scope %q did not provide an effective configuration writer" , selected . scope . scope . Name ) , diagnostics , false )
2026-10-07 13:55:43 +00:00
}
2026-10-11 01:39:23 +00:00
documents = append ( documents , effectiveDocument { name : selected . scope . scope . Name , view : acquired . Value } )
2026-10-07 13:55:43 +00:00
}
2026-10-07 16:47:28 +00:00
if err := invocation . Context . Err ( ) ; err != nil {
2026-10-11 01:39:23 +00:00
return configOperationFailure ( err , diagnostics , false )
2026-10-07 16:47:28 +00:00
}
2026-10-11 01:39:23 +00:00
if len ( documents ) == 1 && plan . scopeName != "all" {
2026-10-07 13:55:43 +00:00
checked := & checkedWriter { writer : invocation . Streams . Out }
renderErr := documents [ 0 ] . view . Effective . WriteEffective ( checked )
if checked . failure != nil {
if renderErr == nil {
renderErr = checked . failure
} else {
renderErr = errors . Join ( renderErr , checked . failure )
}
}
if renderErr != nil {
2026-10-11 01:39:23 +00:00
outcome := configOperationFailure ( renderErr , diagnostics , true )
2026-10-07 13:55:43 +00:00
outcome . DeliveryError = checked . failure
return outcome
}
2026-10-11 01:39:23 +00:00
outcome := commandkit . Success ( )
2026-10-07 13:55:43 +00:00
outcome . Diagnostics = diagnostics
return outcome
}
written := false
for index , document := range documents {
2026-10-07 16:47:28 +00:00
if err := invocation . Context . Err ( ) ; err != nil {
2026-10-11 01:39:23 +00:00
return configOperationFailure ( err , diagnostics , written )
2026-10-07 16:47:28 +00:00
}
2026-10-07 13:55:43 +00:00
var native bytes . Buffer
if err := document . view . Effective . WriteEffective ( & native ) ; err != nil {
2026-10-11 01:39:23 +00:00
return configOperationFailure ( err , diagnostics , written )
2026-10-07 13:55:43 +00:00
}
2026-10-07 16:47:28 +00:00
if err := invocation . Context . Err ( ) ; err != nil {
2026-10-11 01:39:23 +00:00
return configOperationFailure ( err , diagnostics , written )
2026-10-07 16:47:28 +00:00
}
2026-10-09 01:30:17 +00:00
framed , hasDirective := frameEffectiveYAML ( document . name , native . Bytes ( ) )
if index > 0 && hasDirective {
2026-10-11 01:39:23 +00:00
if err := writeConfigReport ( invocation . Streams . Out , [ ] byte ( "...\n" ) ) ; err != nil {
return configDeliveryFailure ( err , diagnostics , true )
2026-10-07 13:55:43 +00:00
}
}
if index < len ( documents ) - 1 && len ( framed ) > 0 && framed [ len ( framed ) - 1 ] != '\n' {
framed = append ( framed , '\n' )
}
2026-10-11 01:39:23 +00:00
if err := writeConfigReport ( invocation . Streams . Out , framed ) ; err != nil {
return configDeliveryFailure ( err , diagnostics , true )
2026-10-07 13:55:43 +00:00
}
written = true
}
2026-10-11 01:39:23 +00:00
outcome := commandkit . Success ( )
2026-10-07 13:55:43 +00:00
outcome . Diagnostics = diagnostics
return outcome
}
2026-10-11 01:39:23 +00:00
type checkedWriter struct {
writer io . Writer
failure error
}
func ( writer * checkedWriter ) Write ( content [ ] byte ) ( int , error ) {
if writer . failure != nil {
return 0 , writer . failure
}
written , err := writer . writer . Write ( content )
if err == nil && written != len ( content ) {
err = io . ErrShortWrite
}
if err != nil {
writer . failure = err
}
return written , err
}
2026-10-09 01:30:17 +00:00
type yamlPreamble struct {
markerStart int
markerEnd int
markerFound bool
inlineMarker bool
preambleEnd int
hasDirective bool
}
func analyzeYAMLPreamble ( native [ ] byte ) yamlPreamble {
var analysis yamlPreamble
for start := 0 ; start < len ( native ) ; {
end := len ( native )
if newline := bytes . IndexByte ( native [ start : ] , '\n' ) ; newline >= 0 {
end = start + newline + 1
}
lineEnd := end
if lineEnd > start && native [ lineEnd - 1 ] == '\n' {
lineEnd --
}
trimmed := bytes . TrimSpace ( native [ start : lineEnd ] )
if isYAMLDocumentStart ( trimmed ) {
content := bytes . TrimSpace ( trimmed [ 3 : ] )
analysis . markerStart = start
analysis . markerEnd = end
analysis . markerFound = true
analysis . inlineMarker = len ( content ) > 0 && content [ 0 ] != '#'
return analysis
2026-10-07 13:55:43 +00:00
}
if bytes . HasPrefix ( trimmed , [ ] byte ( "%YAML " ) ) || bytes . HasPrefix ( trimmed , [ ] byte ( "%TAG " ) ) {
2026-10-09 01:30:17 +00:00
analysis . hasDirective = true
2026-10-07 13:55:43 +00:00
}
2026-10-09 01:30:17 +00:00
if len ( trimmed ) == 0 || trimmed [ 0 ] == '#' || bytes . HasPrefix ( trimmed , [ ] byte ( "%YAML " ) ) || bytes . HasPrefix ( trimmed , [ ] byte ( "%TAG " ) ) {
analysis . preambleEnd = end
} else {
return analysis
2026-10-07 13:55:43 +00:00
}
2026-10-09 01:30:17 +00:00
start = end
2026-10-07 13:55:43 +00:00
}
2026-10-09 01:30:17 +00:00
return analysis
2026-10-07 13:55:43 +00:00
}
2026-10-09 01:30:17 +00:00
func frameEffectiveYAML ( scope string , native [ ] byte ) ( [ ] byte , bool ) {
analysis := analyzeYAMLPreamble ( native )
2026-10-07 13:55:43 +00:00
label := scope
2026-10-11 01:39:23 +00:00
for _ , character := range scope {
if unicode . IsControl ( character ) {
2026-10-07 13:55:43 +00:00
label = strconv . Quote ( scope )
break
}
}
comment := [ ] byte ( "# scope: " + label + "\n" )
2026-10-09 01:30:17 +00:00
if analysis . markerFound {
out := make ( [ ] byte , 0 , len ( native ) + len ( comment ) )
if analysis . inlineMarker {
out = append ( out , native [ : analysis . markerStart ] ... )
2026-10-07 13:55:43 +00:00
out = append ( out , comment ... )
2026-10-09 01:30:17 +00:00
out = append ( out , native [ analysis . markerStart : ] ... )
return out , analysis . hasDirective
2026-10-07 13:55:43 +00:00
}
2026-10-09 01:30:17 +00:00
out = append ( out , native [ : analysis . markerEnd ] ... )
if analysis . markerEnd > analysis . markerStart && native [ analysis . markerEnd - 1 ] != '\n' {
out = append ( out , '\n' )
2026-10-07 13:55:43 +00:00
}
2026-10-09 01:30:17 +00:00
out = append ( out , comment ... )
out = append ( out , native [ analysis . markerEnd : ] ... )
return out , analysis . hasDirective
2026-10-07 13:55:43 +00:00
}
result := make ( [ ] byte , 0 , len ( native ) + len ( comment ) + 5 )
2026-10-09 01:30:17 +00:00
if analysis . hasDirective {
result = append ( result , native [ : analysis . preambleEnd ] ... )
2026-10-07 13:55:43 +00:00
}
result = append ( result , [ ] byte ( "---\n" ) ... )
result = append ( result , comment ... )
2026-10-09 01:30:17 +00:00
if analysis . hasDirective {
result = append ( result , native [ analysis . preambleEnd : ] ... )
2026-10-07 13:55:43 +00:00
} else {
result = append ( result , native ... )
}
2026-10-09 01:30:17 +00:00
return result , analysis . hasDirective
2026-10-07 13:55:43 +00:00
}
2026-10-09 01:30:17 +00:00
func isYAMLDocumentStart ( line [ ] byte ) bool {
return bytes . HasPrefix ( line , [ ] byte ( "---" ) ) && ( len ( line ) == 3 || line [ 3 ] == ' ' || line [ 3 ] == '\t' )
2026-10-07 16:45:10 +00:00
}