mirror of
https://github.com/awalsh128/cache-apt-pkgs-action.git
synced 2025-12-28 22:31:26 +00:00
100 lines
2.6 KiB
Go
100 lines
2.6 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"mvdan.cc/sh/v3/syntax"
|
|
)
|
|
|
|
// ParseBashToAST parses a bash script string into an AST
|
|
func ParseBashToAST(script string) (*syntax.File, error) {
|
|
// Create a new parser with bash dialect
|
|
parser := syntax.NewParser(syntax.KeepComments(true), syntax.Variant(syntax.LangBash))
|
|
|
|
// Parse the script into an AST
|
|
file, err := parser.Parse(strings.NewReader(script), "")
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to parse bash script: %v", err)
|
|
}
|
|
|
|
return file, nil
|
|
}
|
|
|
|
// AnalyzeBashScript provides analysis of a bash script including variables, functions, and commands
|
|
func AnalyzeBashScript(script string) (map[string]interface{}, error) {
|
|
file, err := ParseBashToAST(script)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
analysis := make(map[string]interface{})
|
|
variables := make(map[string]struct{})
|
|
functions := make([]string, 0)
|
|
commands := make([]string, 0)
|
|
|
|
// Walk the AST and collect information
|
|
syntax.Walk(file, func(node syntax.Node) bool {
|
|
switch n := node.(type) {
|
|
case *syntax.Assign:
|
|
// Found variable assignment
|
|
if n.Name != nil {
|
|
variables[n.Name.Value] = struct{}{}
|
|
}
|
|
case *syntax.FuncDecl:
|
|
// Found function declaration
|
|
if n.Name != nil {
|
|
functions = append(functions, n.Name.Value)
|
|
}
|
|
case *syntax.CallExpr:
|
|
// Found command execution
|
|
if len(n.Args) > 0 {
|
|
var cmd strings.Builder
|
|
for _, part := range n.Args[0].Parts {
|
|
if lit, ok := part.(*syntax.Lit); ok {
|
|
cmd.WriteString(lit.Value)
|
|
}
|
|
}
|
|
if cmd.Len() > 0 {
|
|
commands = append(commands, cmd.String())
|
|
}
|
|
}
|
|
}
|
|
return true
|
|
})
|
|
|
|
// Convert variables map to slice for better JSON output
|
|
varSlice := make([]string, 0, len(variables))
|
|
for v := range variables {
|
|
varSlice = append(varSlice, v)
|
|
}
|
|
|
|
analysis["variables"] = varSlice
|
|
analysis["functions"] = functions
|
|
analysis["commands"] = commands
|
|
|
|
return analysis, nil
|
|
}
|
|
|
|
func ParseAndGetAst(action Action) (string, error) {
|
|
converter := NewBashConverter(action)
|
|
script := converter.Convert()
|
|
|
|
// Analyze the generated script
|
|
analysis, err := AnalyzeBashScript(script)
|
|
if err != nil {
|
|
return script, fmt.Errorf("script analysis error: %v", err)
|
|
}
|
|
|
|
// Add analysis as comments at the top of the script
|
|
var finalScript strings.Builder
|
|
finalScript.WriteString("#!/bin/bash\n\n")
|
|
finalScript.WriteString("# Script Analysis:\n")
|
|
finalScript.WriteString(fmt.Sprintf("# Variables: %v\n", analysis["variables"]))
|
|
finalScript.WriteString(fmt.Sprintf("# Functions: %v\n", analysis["functions"]))
|
|
finalScript.WriteString(fmt.Sprintf("# Commands: %v\n\n", analysis["commands"]))
|
|
finalScript.WriteString(script)
|
|
|
|
return finalScript.String(), nil
|
|
}
|