initial commit (second try)
This commit is contained in:
parent
a62cf65376
commit
ed3c0eae14
7 changed files with 656 additions and 0 deletions
226
commands.go
Normal file
226
commands.go
Normal file
|
@ -0,0 +1,226 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func initCommand(lang string) error {
|
||||
if lang == "" {
|
||||
fmt.Println("Building base hako image...")
|
||||
return buildBaseImage()
|
||||
}
|
||||
|
||||
if !imageExists("hako-userland") {
|
||||
fmt.Println("Base image not found, building it first...")
|
||||
if err := buildBaseImage(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("Building %s language image...\n", lang)
|
||||
return buildLanguageImage(lang)
|
||||
}
|
||||
|
||||
func upCommand(lang string) error {
|
||||
containerName, err := getProjectContainerName(lang)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
imageName := fmt.Sprintf("hako-userland-%s", lang)
|
||||
if !imageExists(imageName) {
|
||||
return fmt.Errorf("image %s not found, run 'hako init %s' first", imageName, lang)
|
||||
}
|
||||
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if containerExists(containerName) {
|
||||
if !containerIsRunning(containerName) {
|
||||
fmt.Printf("Starting existing container %s...\n", containerName)
|
||||
if err := startContainer(containerName); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("Container %s is already running\n", containerName)
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("Creating new container %s...\n", containerName)
|
||||
if err := createContainer(containerName, imageName, cwd); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := startContainer(containerName); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("Copying workspace to container...\n")
|
||||
if err := copyWorkspaceToContainer(containerName); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("Entering container %s...\n", containerName)
|
||||
return execContainer(containerName)
|
||||
}
|
||||
|
||||
func downCommand(container string) error {
|
||||
var containerName string
|
||||
|
||||
if container != "" {
|
||||
containerName = container
|
||||
} else {
|
||||
// Find any hako container for current project
|
||||
output, err := runCommandOutput("docker", "ps", "-a", "--filter", "name=hako-", "--format", "{{.Names}}")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
containers := strings.Split(strings.TrimSpace(output), "\n")
|
||||
if len(containers) == 0 || containers[0] == "" {
|
||||
return fmt.Errorf("no hako containers found for current project")
|
||||
}
|
||||
containerName = containers[0] // Use first found container
|
||||
}
|
||||
|
||||
if !containerExists(containerName) {
|
||||
return fmt.Errorf("container %s does not exist", containerName)
|
||||
}
|
||||
|
||||
fmt.Printf("Stopping container %s...\n", containerName)
|
||||
if containerIsRunning(containerName) {
|
||||
if err := stopContainer(containerName); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("Removing container %s...\n", containerName)
|
||||
return removeContainer(containerName)
|
||||
}
|
||||
|
||||
func psCommand() error {
|
||||
fmt.Println("Hako containers:")
|
||||
return listHakoContainers()
|
||||
}
|
||||
|
||||
func syncCommand() error {
|
||||
output, err := runCommandOutput("docker", "ps", "-a", "--filter", "name=hako-", "--format", "{{.Names}}")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
containers := strings.Split(strings.TrimSpace(output), "\n")
|
||||
if len(containers) == 0 || containers[0] == "" {
|
||||
return fmt.Errorf("no hako containers found for current project")
|
||||
}
|
||||
containerName := containers[0] // Use first found container
|
||||
|
||||
if !containerExists(containerName) {
|
||||
return fmt.Errorf("container %s does not exist", containerName)
|
||||
}
|
||||
|
||||
fmt.Printf("Syncing files from container %s...\n", containerName)
|
||||
|
||||
tempDir, err := os.MkdirTemp("", "hako-sync-*")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.RemoveAll(tempDir)
|
||||
|
||||
if err := copyFromContainer(containerName, "/workspace/.", tempDir); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return syncFiles(tempDir, ".")
|
||||
}
|
||||
|
||||
func syncFiles(srcDir, destDir string) error {
|
||||
return filepath.Walk(srcDir, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
relPath, err := filepath.Rel(srcDir, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if relPath == ".git" || relPath == ".gitignore" {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
|
||||
if strings.HasPrefix(filepath.Base(relPath), ".git") {
|
||||
return nil
|
||||
}
|
||||
|
||||
destPath := filepath.Join(destDir, relPath)
|
||||
|
||||
if info.IsDir() {
|
||||
return os.MkdirAll(destPath, info.Mode())
|
||||
}
|
||||
|
||||
srcFile, err := os.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer srcFile.Close()
|
||||
|
||||
destFile, err := os.Create(destPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer destFile.Close()
|
||||
|
||||
_, err = io.Copy(destFile, srcFile)
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
func copyWorkspaceToContainer(containerName string) error {
|
||||
// Get all files that should be copied (tracked + untracked, excluding ignored)
|
||||
trackedFiles, err := runCommandOutput("git", "ls-files")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
untrackedFiles, err := runCommandOutput("git", "ls-files", "--others", "--exclude-standard")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
allFiles := []string{}
|
||||
if trackedFiles != "" {
|
||||
allFiles = append(allFiles, strings.Split(trackedFiles, "\n")...)
|
||||
}
|
||||
if untrackedFiles != "" {
|
||||
allFiles = append(allFiles, strings.Split(untrackedFiles, "\n")...)
|
||||
}
|
||||
|
||||
if len(allFiles) == 0 {
|
||||
return fmt.Errorf("no files to copy")
|
||||
}
|
||||
|
||||
// Copy files one by one to preserve directory structure
|
||||
for _, file := range allFiles {
|
||||
if file == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
// Create directory structure in container if needed
|
||||
dir := filepath.Dir(file)
|
||||
if dir != "." {
|
||||
if err := runCommand("docker", "exec", containerName, "mkdir", "-p", "/workspace/"+dir); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the file
|
||||
if err := copyToContainer(containerName, file, "/workspace/"+file); err != nil {
|
||||
return fmt.Errorf("failed to copy %s: %v", file, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue