Skip to content

Commit e9d0258

Browse files
committed
starting the build/run commands
1 parent a46558c commit e9d0258

3 files changed

Lines changed: 304 additions & 1 deletion

File tree

tsunami/build/build.go

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
package build
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"os"
7+
"path/filepath"
8+
"strings"
9+
)
10+
11+
type BuildOpts struct {
12+
Dir string
13+
Verbose bool
14+
}
15+
16+
func verifyTsunamiDir(dir string) error {
17+
if dir == "" {
18+
return fmt.Errorf("directory path cannot be empty")
19+
}
20+
21+
// Check if directory exists
22+
info, err := os.Stat(dir)
23+
if err != nil {
24+
if os.IsNotExist(err) {
25+
return fmt.Errorf("directory %q does not exist", dir)
26+
}
27+
return fmt.Errorf("error accessing directory %q: %w", dir, err)
28+
}
29+
30+
if !info.IsDir() {
31+
return fmt.Errorf("%q is not a directory", dir)
32+
}
33+
34+
// Check for app.go file
35+
appGoPath := filepath.Join(dir, "app.go")
36+
if err := CheckFileExists(appGoPath); err != nil {
37+
return fmt.Errorf("app.go check failed in directory %q: %w", dir, err)
38+
}
39+
40+
// Check static directory if it exists
41+
staticPath := filepath.Join(dir, "static")
42+
if err := IsDirOrNotFound(staticPath); err != nil {
43+
return fmt.Errorf("static directory check failed in %q: %w", dir, err)
44+
}
45+
46+
// Check that dist doesn't exist
47+
distPath := filepath.Join(dir, "dist")
48+
if err := FileMustNotExist(distPath); err != nil {
49+
return fmt.Errorf("dist check failed in %q: %w", dir, err)
50+
}
51+
52+
return nil
53+
}
54+
55+
func TsunamiBuild(opts BuildOpts) error {
56+
if err := verifyTsunamiDir(opts.Dir); err != nil {
57+
return err
58+
}
59+
60+
// Create temporary directory
61+
tempDir, err := os.MkdirTemp("", "tsunami-build-*")
62+
if err != nil {
63+
return fmt.Errorf("failed to create temp directory: %w", err)
64+
}
65+
66+
log.Printf("Building tsunami app from %s\n", opts.Dir)
67+
68+
if opts.Verbose {
69+
log.Printf("Temp dir: %s\n", tempDir)
70+
}
71+
72+
// Copy all *.go files from the root directory
73+
goCount, err := copyGoFiles(opts.Dir, tempDir)
74+
if err != nil {
75+
return fmt.Errorf("failed to copy go files: %w", err)
76+
}
77+
78+
// Copy static directory
79+
staticCount, err := copyStaticDir(opts.Dir, tempDir)
80+
if err != nil {
81+
return fmt.Errorf("failed to copy static directory: %w", err)
82+
}
83+
84+
// Create dist directory
85+
distDir := filepath.Join(tempDir, "dist")
86+
if err := os.MkdirAll(distDir, 0755); err != nil {
87+
return fmt.Errorf("failed to create dist directory: %w", err)
88+
}
89+
90+
if opts.Verbose {
91+
log.Printf("Copied %d go files, %d static files\n", goCount, staticCount)
92+
}
93+
return nil
94+
}
95+
96+
func copyStaticDir(srcDir, destDir string) (int, error) {
97+
// Always create static directory in temp dir
98+
staticDestDir := filepath.Join(destDir, "static")
99+
if err := os.MkdirAll(staticDestDir, 0755); err != nil {
100+
return 0, fmt.Errorf("failed to create static directory: %w", err)
101+
}
102+
103+
// Copy static/ directory contents if it exists
104+
staticSrcDir := filepath.Join(srcDir, "static")
105+
if _, err := os.Stat(staticSrcDir); err == nil {
106+
return copyDirRecursive(staticSrcDir, staticDestDir)
107+
}
108+
109+
return 0, nil
110+
}
111+
112+
func copyGoFiles(srcDir, destDir string) (int, error) {
113+
entries, err := os.ReadDir(srcDir)
114+
if err != nil {
115+
return 0, err
116+
}
117+
118+
fileCount := 0
119+
for _, entry := range entries {
120+
if entry.IsDir() {
121+
continue
122+
}
123+
124+
if strings.HasSuffix(entry.Name(), ".go") {
125+
srcPath := filepath.Join(srcDir, entry.Name())
126+
destPath := filepath.Join(destDir, entry.Name())
127+
128+
if err := copyFile(srcPath, destPath); err != nil {
129+
return 0, fmt.Errorf("failed to copy %s: %w", entry.Name(), err)
130+
}
131+
fileCount++
132+
}
133+
}
134+
135+
return fileCount, nil
136+
}
137+
138+
func TsunamiRun(opts BuildOpts) error {
139+
if err := TsunamiBuild(opts); err != nil {
140+
return err
141+
}
142+
143+
return fmt.Errorf("TsunamiRun not implemented yet")
144+
}

tsunami/build/buildutil.go

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
package build
2+
3+
import (
4+
"fmt"
5+
"io"
6+
"os"
7+
"path/filepath"
8+
)
9+
10+
func IsDirOrNotFound(path string) error {
11+
info, err := os.Stat(path)
12+
if err != nil {
13+
if os.IsNotExist(err) {
14+
return nil // Not found is OK
15+
}
16+
return err // Other errors are not OK
17+
}
18+
19+
if !info.IsDir() {
20+
return fmt.Errorf("%q exists but is not a directory", path)
21+
}
22+
23+
return nil // It's a directory, which is OK
24+
}
25+
26+
func CheckFileExists(path string) error {
27+
info, err := os.Stat(path)
28+
if err != nil {
29+
if os.IsNotExist(err) {
30+
return fmt.Errorf("file %q not found", path)
31+
}
32+
return fmt.Errorf("error accessing file %q: %w", path, err)
33+
}
34+
35+
if info.IsDir() {
36+
return fmt.Errorf("%q is a directory, not a file", path)
37+
}
38+
39+
return nil
40+
}
41+
42+
func FileMustNotExist(path string) error {
43+
if _, err := os.Stat(path); err == nil {
44+
return fmt.Errorf("%q must not exist", path)
45+
} else if !os.IsNotExist(err) {
46+
return err // Other errors are not OK
47+
}
48+
return nil // Not found is OK
49+
}
50+
51+
func copyDirRecursive(srcDir, destDir string) (int, error) {
52+
fileCount := 0
53+
err := filepath.Walk(srcDir, func(path string, info os.FileInfo, err error) error {
54+
if err != nil {
55+
return err
56+
}
57+
58+
// Calculate destination path
59+
relPath, err := filepath.Rel(srcDir, path)
60+
if err != nil {
61+
return err
62+
}
63+
destPath := filepath.Join(destDir, relPath)
64+
65+
if info.IsDir() {
66+
// Create directory
67+
if err := os.MkdirAll(destPath, info.Mode()); err != nil {
68+
return err
69+
}
70+
} else {
71+
// Copy file
72+
if err := copyFile(path, destPath); err != nil {
73+
return err
74+
}
75+
fileCount++
76+
}
77+
78+
return nil
79+
})
80+
81+
return fileCount, err
82+
}
83+
84+
func copyFile(srcPath, destPath string) error {
85+
// Get source file info for mode
86+
srcInfo, err := os.Stat(srcPath)
87+
if err != nil {
88+
return err
89+
}
90+
91+
// Create destination directory if it doesn't exist
92+
destDir := filepath.Dir(destPath)
93+
if err := os.MkdirAll(destDir, 0755); err != nil {
94+
return err
95+
}
96+
97+
srcFile, err := os.Open(srcPath)
98+
if err != nil {
99+
return err
100+
}
101+
defer srcFile.Close()
102+
103+
destFile, err := os.Create(destPath)
104+
if err != nil {
105+
return err
106+
}
107+
defer destFile.Close()
108+
109+
_, err = io.Copy(destFile, srcFile)
110+
if err != nil {
111+
return err
112+
}
113+
114+
// Set the same mode as source file
115+
return os.Chmod(destPath, srcInfo.Mode())
116+
}

tsunami/cmd/main-tsunami.go

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"os"
66

77
"github.com/spf13/cobra"
8+
"github.com/wavetermdev/waveterm/tsunami/build"
89
"github.com/wavetermdev/waveterm/tsunami/tsunamibase"
910
)
1011

@@ -27,8 +28,50 @@ var versionCmd = &cobra.Command{
2728
},
2829
}
2930

31+
var buildCmd = &cobra.Command{
32+
Use: "build [directory]",
33+
Short: "Build a Tsunami application",
34+
Long: `Build a Tsunami application from the specified directory.`,
35+
Args: cobra.ExactArgs(1),
36+
Run: func(cmd *cobra.Command, args []string) {
37+
verbose, _ := cmd.Flags().GetBool("verbose")
38+
opts := build.BuildOpts{
39+
Dir: args[0],
40+
Verbose: verbose,
41+
}
42+
if err := build.TsunamiBuild(opts); err != nil {
43+
fmt.Printf("Build failed: %v\n", err)
44+
os.Exit(1)
45+
}
46+
},
47+
}
48+
49+
var runCmd = &cobra.Command{
50+
Use: "run [directory]",
51+
Short: "Build and run a Tsunami application",
52+
Long: `Build and run a Tsunami application from the specified directory.`,
53+
Args: cobra.ExactArgs(1),
54+
Run: func(cmd *cobra.Command, args []string) {
55+
verbose, _ := cmd.Flags().GetBool("verbose")
56+
opts := build.BuildOpts{
57+
Dir: args[0],
58+
Verbose: verbose,
59+
}
60+
if err := build.TsunamiRun(opts); err != nil {
61+
fmt.Printf("Run failed: %v\n", err)
62+
os.Exit(1)
63+
}
64+
},
65+
}
66+
3067
func init() {
3168
rootCmd.AddCommand(versionCmd)
69+
70+
buildCmd.Flags().BoolP("verbose", "v", false, "Enable verbose output")
71+
rootCmd.AddCommand(buildCmd)
72+
73+
runCmd.Flags().BoolP("verbose", "v", false, "Enable verbose output")
74+
rootCmd.AddCommand(runCmd)
3275
}
3376

3477
func main() {
@@ -37,4 +80,4 @@ func main() {
3780
fmt.Println(err)
3881
os.Exit(1)
3982
}
40-
}
83+
}

0 commit comments

Comments
 (0)