Skip to content

Commit 7a78f18

Browse files
author
Florian Heinze
committed
FEATURE: check if task exists in dev.sh and give hint if not
1 parent 427b6b4 commit 7a78f18

File tree

2 files changed

+106
-28
lines changed

2 files changed

+106
-28
lines changed

dev.sh

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,28 @@ set -e
1111

1212
######### TASKS #########
1313

14+
function foo_bar() {
15+
echo "#### TEST ####"
16+
}
17+
18+
function foo-foo(){
19+
echo "#### TEST ####"
20+
}
21+
22+
function foo3 () {
23+
echo "#### TEST ####"
24+
}
25+
26+
function foo1() {
27+
echo "#### TEST ####"
28+
_log_success "SUCCESS"
29+
_log_warning "WARNING"
30+
_log_success "Arguments"
31+
_log_success ' $0: '"$0"
32+
_log_success ' $1: '"$1"
33+
_log_success ' $2: '"$2"
34+
}
35+
1436
function test() {
1537
echo "#### TEST ####"
1638
_log_success "SUCCESS"
@@ -42,3 +64,4 @@ _log_error() {
4264
# THIS NEEDS TO BE LAST!!!
4365
# this will run your tasks
4466
"$@"
67+

main.go

Lines changed: 83 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"os"
1010
"path/filepath"
1111
"regexp"
12+
"sort"
1213
"strings"
1314
"syscall"
1415
)
@@ -28,7 +29,7 @@ var Assets embed.FS
2829

2930
func main() {
3031
// `os.Args[0]` will always be the path of the script
31-
// `os.Args[1]` will either be INIT or a task of the dev.sh script
32+
// `os.Args[1]` will either be INIT or a name of the dev.sh script
3233
if len(os.Args) > 1 {
3334
if os.Args[1] == INIT_ARGUMENT {
3435
// If we called `dev INIT`
@@ -44,7 +45,7 @@ func main() {
4445
} else {
4546
// Show usage
4647
fmt.Println(aurora.Bold("USAGE:"))
47-
fmt.Println(" ", aurora.Bold("dev <TASK_NAME>"), "- to run a task of your dev.sh")
48+
fmt.Println(" ", aurora.Bold("dev <TASK_NAME>"), "- to run a name of your dev.sh")
4849
fmt.Println(" ", aurora.Bold("dev INIT"), "- to create a `dev.sh` in the current folder")
4950
// Explicitly show that we exit here
5051
os.Exit(0)
@@ -88,23 +89,19 @@ func runTask() {
8889
for {
8990
devScriptPath := filepath.Join(currentDirectory, DEV_SCRIPT_NAME)
9091
if fileExists(devScriptPath) {
91-
fmt.Println(aurora.Magenta(LOGGING_PREFIX + "Found " + DEV_SCRIPT_NAME + " in "))
92-
fmt.Println(aurora.Magenta(LOGGING_WSPACE + currentDirectory))
92+
fmt.Println(aurora.Magenta(LOGGING_PREFIX + "Found " + currentDirectory + "/" + DEV_SCRIPT_NAME))
9393
if fileContains(devScriptPath, DEV_SCRIPT_MARKER) {
94-
fmt.Println(aurora.Magenta(LOGGING_PREFIX + "Found marker in "))
95-
fmt.Println(aurora.Magenta(LOGGING_WSPACE + currentDirectory + "/" + DEV_SCRIPT_NAME))
94+
fmt.Println(aurora.Magenta(LOGGING_WSPACE + "Found marker '" + DEV_SCRIPT_MARKER + "'"))
9695
execDevScriptWithArguments(devScriptPath, os.Args[1:])
9796
break
9897
} else {
99-
fmt.Println(aurora.Yellow(LOGGING_PREFIX + "Marker '" + DEV_SCRIPT_MARKER + "' is missing in "))
100-
fmt.Println(aurora.Yellow(LOGGING_WSPACE + currentDirectory + "/" + DEV_SCRIPT_NAME))
101-
fmt.Println(aurora.Yellow(LOGGING_WSPACE + "Moving up, looking for " + DEV_SCRIPT_NAME))
98+
fmt.Println(aurora.Yellow(LOGGING_WSPACE + "Marker '" + DEV_SCRIPT_MARKER + "' is missing in " + DEV_SCRIPT_NAME))
99+
fmt.Println(aurora.Yellow(LOGGING_WSPACE + "Moving up, looking for new " + DEV_SCRIPT_NAME))
102100
// Not breaking here as we want to move up
103101
}
104102
}
105103
if currentDirectory == "/" || steps >= MAX_DEPTH {
106-
fmt.Println(aurora.Yellow(aurora.Bold(LOGGING_PREFIX + "No " + DEV_SCRIPT_NAME + " with " + DEV_SCRIPT_MARKER + " found")))
107-
fmt.Println(aurora.Yellow(aurora.Bold(LOGGING_WSPACE + "Nothing to do here :(")))
104+
fmt.Println(aurora.Yellow(aurora.Bold(LOGGING_PREFIX + "No " + DEV_SCRIPT_NAME + " with " + DEV_SCRIPT_MARKER + " found. Nothing to do here :(")))
108105
fmt.Println(aurora.Magenta(aurora.Bold(LOGGING_BAR)))
109106
break
110107
}
@@ -147,27 +144,85 @@ func copyAssetToPath(embedPath string, targetPath string) {
147144
fmt.Println(aurora.Magenta(LOGGING_PREFIX + targetPath + " was created."))
148145
}
149146

150-
func execDevScriptWithArguments(devScriptPath string, arguments []string) {
151-
fmt.Println(aurora.Magenta(aurora.Bold(LOGGING_PREFIX + "Executing dev script :)")))
152-
fmt.Println(aurora.Magenta(aurora.Bold(LOGGING_BAR)))
153-
err := os.Chdir(filepath.Dir(devScriptPath))
154-
if err != nil {
155-
log.Fatalf("Failed to execute: '%s'", err.Error())
147+
type DevScriptTask struct {
148+
name string
149+
comments string
150+
}
151+
152+
func taskExists(tasks []DevScriptTask, calledTask string) bool {
153+
for _, task := range tasks {
154+
if task.name == calledTask {
155+
return true
156+
}
157+
}
158+
return false
159+
}
160+
161+
func availableTasks(tasks []DevScriptTask) string {
162+
result := ""
163+
for _, task := range tasks {
164+
result += LOGGING_WSPACE + " " + task.name + "\n"
156165
}
157-
// In case the script is not executable
158-
err = os.Chmod(devScriptPath, 0755)
166+
return result
167+
}
168+
169+
func parseDevScriptTasks(devScriptPath string) []DevScriptTask {
170+
// https://regex101.com/r/5LVRcP/1 -> Iteration 1 without comments before
171+
// https://regex101.com/r/XyB410/1 -> Final Iteration with comments before ;)
172+
devScriptBytes, err := os.ReadFile(devScriptPath)
159173
if err != nil {
160174
log.Fatalf("Failed to execute: '%s'", err.Error())
161175
}
162176

163-
// We tried using exec.Command(devScriptPath, arguments...) which failed for interactive
164-
// terminal calls, e.g. `docker compose exec neos /bin/bash` This is running our command
165-
// as a child process. We are now replacing the process of this helper with the call of
166-
// the `dev.sh` using `syscall.Exec()`
167-
err = syscall.Exec(devScriptPath, append([]string{devScriptPath}, arguments...), os.Environ())
168-
if err != nil {
169-
log.Fatalf("Failed to run shell script: '%s'", err.Error())
177+
devScriptString := string(devScriptBytes)
178+
compiledRegex := regexp.MustCompile(`(?m)(?P<comments>(?:^#.*(?:\n|\r\n|\r))*)^(?:function )?(?P<name>[a-zA-Z0-9_-]+)\s?(?:\(\))?\s?{`)
179+
captureGroupNames := compiledRegex.SubexpNames()
180+
commentsIndex := sort.StringSlice(captureGroupNames).Search("comments")
181+
taskIndex := sort.StringSlice(captureGroupNames).Search("name")
182+
matches := compiledRegex.FindAllStringSubmatch(devScriptString, -1)
183+
184+
var results = []DevScriptTask{}
185+
for _, match := range matches {
186+
task := match[taskIndex]
187+
comments := match[commentsIndex]
188+
if !strings.HasPrefix(task, "_") {
189+
results = append(results, DevScriptTask{name: task, comments: comments})
190+
}
191+
}
192+
return results
193+
}
194+
195+
func execDevScriptWithArguments(devScriptPath string, arguments []string) {
196+
tasks := parseDevScriptTasks(devScriptPath)
197+
calledTask := os.Args[1]
198+
if taskExists(tasks, calledTask) {
199+
fmt.Println(aurora.Magenta(LOGGING_WSPACE + "Found task '" + calledTask + "'"))
200+
fmt.Println(aurora.Magenta(aurora.Bold(LOGGING_PREFIX + "Executing dev script :)")))
201+
fmt.Println(aurora.Magenta(aurora.Bold(LOGGING_BAR)))
202+
err := os.Chdir(filepath.Dir(devScriptPath))
203+
if err != nil {
204+
log.Fatalf("Failed to execute: '%s'", err.Error())
205+
}
206+
// In case the script is not executable
207+
err = os.Chmod(devScriptPath, 0755)
208+
if err != nil {
209+
log.Fatalf("Failed to execute: '%s'", err.Error())
210+
}
211+
212+
// We tried using exec.Command(devScriptPath, arguments...) which failed for interactive
213+
// terminal calls, e.g. `docker compose exec neos /bin/bash` This is running our command
214+
// as a child process. We are now replacing the process of this helper with the call of
215+
// the `dev.sh` using `syscall.Exec()`
216+
err = syscall.Exec(devScriptPath, append([]string{devScriptPath}, arguments...), os.Environ())
217+
if err != nil {
218+
log.Fatalf("Failed to run shell script: '%s'", err.Error())
219+
}
220+
// IMPORTANT: As we are replacing the process of the helper nothing else will be
221+
// called, except the error handler!
222+
} else {
223+
fmt.Println(aurora.Yellow(aurora.Bold(LOGGING_WSPACE + "No task '" + calledTask + "' found. Nothing to do here :(")))
224+
fmt.Println(aurora.Yellow(aurora.Bold(LOGGING_WSPACE + "Try one of the following:")))
225+
fmt.Print(aurora.Yellow(availableTasks(tasks)))
226+
fmt.Println(aurora.Magenta(aurora.Bold(LOGGING_BAR)))
170227
}
171-
// IMPORTANT: As we are replacing the process of the helper nothing else will be
172-
// called, except the error handler!
173228
}

0 commit comments

Comments
 (0)