Skip to content

Commit

Permalink
Merge pull request #35 from mikoto2000/update-error-handling
Browse files Browse the repository at this point in the history
Update error handling in main.go
  • Loading branch information
mikoto2000 authored Oct 30, 2024
2 parents 9dc37ee + 35032fe commit 8c68e81
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 26 deletions.
10 changes: 9 additions & 1 deletion devcontainer/devcontainer.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ const containerCommand = "docker"

var devcontainreArgsPrefix = []string{"up"}

type UnknownTypeError struct {
msg string
}

func (e *UnknownTypeError) Error() string {
return e.msg
}

// devcontainer でコンテナを立ち上げ、 Vim を転送し、実行する。
// 既存実装の都合上、configFilePath から configDirForDevcontainer を抽出している
func ExecuteDevcontainer(args []string, devcontainerPath string, vimFilePath string, cdrPath, configFilePath string, vimrc string) error {
Expand Down Expand Up @@ -359,7 +367,7 @@ func findDockerComposeFileDir() (string, error) {
vv := v[0].(string)
dockerComposeFilePath = filepath.Join(devcontainerJSONDir, vv)
default:
return "", errors.New("unknown type")
return "", &UnknownTypeError{msg: "unknown type"}
}
dockerComposeFileDir := filepath.Dir(dockerComposeFilePath)

Expand Down
11 changes: 9 additions & 2 deletions devcontainer/readConfigurationResult.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,16 @@ package devcontainer

import (
"encoding/json"
"errors"
)

type ReadConfigurationError struct {
msg string
}

func (e *ReadConfigurationError) Error() string {
return e.msg
}

// `devcontainers read-configuration` コマンドの実行結果スキーマ
//
// Example: {
Expand Down Expand Up @@ -42,7 +49,7 @@ type ConfigFilePath struct {
func GetConfigFilePath(readConfigurationCommandResult string) (string, error) {
result, err := UnmarshalReadConfigurationCommandResult([]byte(readConfigurationCommandResult))
if err != nil {
return "", errors.New("`devcontainer read-configuration` の出力パースに失敗しました。`.devcontainer.json が存在することと、 docker エンジンが起動していることを確認してください。")
return "", &ReadConfigurationError{msg: "`devcontainer read-configuration` の出力パースに失敗しました。`.devcontainer.json が存在することと、 docker エンジンが起動していることを確認してください。"}
}

return result.Configuration.ConfigFilePath.FsPath, nil
Expand Down
31 changes: 27 additions & 4 deletions docker/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package docker

import (
"context"
"errors"
"fmt"
"os"
"os/exec"
Expand All @@ -19,6 +18,30 @@ const containerCommand = "docker"
var dockerRunArgsPrefix = []string{"run", "-d", "--rm"}
var dockerRunArgsSuffix = []string{"sh", "-c", "trap \"exit 0\" TERM; sleep infinity & wait"}

type ContainerStartError struct {
msg string
}

func (e *ContainerStartError) Error() string {
return e.msg
}

type ChmodError struct {
msg string
}

func (e *ChmodError) Error() string {
return e.msg
}

type ContainerNotFoundError struct {
msg string
}

func (e *ContainerNotFoundError) Error() string {
return e.msg
}

func Run(args []string, vimFilePath string, cdrPath string, configDirForDocker string, vimrc string, defaultRunargs []string) error {
vimFileName := filepath.Base(vimFilePath)

Expand All @@ -38,7 +61,7 @@ func Run(args []string, vimFilePath string, cdrPath string, configDirForDocker s
if err != nil {
fmt.Fprintln(os.Stderr, "Container start error.")
fmt.Fprintln(os.Stderr, string(containerID))
return err
return &ContainerStartError{msg: "Container start error."}
}
containerID = strings.ReplaceAll(containerID, "\n", "")
containerID = strings.ReplaceAll(containerID, "\r", "")
Expand Down Expand Up @@ -70,7 +93,7 @@ func Run(args []string, vimFilePath string, cdrPath string, configDirForDocker s
if err != nil {
fmt.Fprintln(os.Stderr, "chmod error.")
fmt.Fprintln(os.Stderr, string(chmodResult))
return err
return &ChmodError{msg: "chmod error."}
}
fmt.Printf(" done.\n")

Expand Down Expand Up @@ -152,7 +175,7 @@ func GetContainerIDFromWorkspaceFolder(workspaceFolder string) (string, error) {

psResult, err := Ps("label=devcontainer.local_folder=" + workspaceFilderAbs)
if psResult == "" {
return "", errors.New("container not found.")
return "", &ContainerNotFoundError{msg: "container not found."}
}
if err != nil {
return "", err
Expand Down
42 changes: 37 additions & 5 deletions dockercompose/dockerCompose.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,52 @@ import (
"os/exec"
)

type PsCommandError struct {
msg string
}

func (e *PsCommandError) Error() string {
return e.msg
}

type StopCommandError struct {
msg string
}

func (e *StopCommandError) Error() string {
return e.msg
}

type DownCommandError struct {
msg string
}

func (e *DownCommandError) Error() string {
return e.msg
}

// `docker compose ps --format json` を実行し、結果の文字列を返却する。
func Ps(workspaceFolder string) (string, error) {

// 現在のディレクトリを記憶
currentDirectory, err := os.Getwd()
if err != nil {
return "", err
return "", &PsCommandError{msg: "Failed to get current directory"}
}

// 元のディレクトリへ戻る
defer func() error {
err := os.Chdir(currentDirectory)
if err != nil {
return err
return &PsCommandError{msg: "Failed to change directory"}
}
return nil
}()

// ワークスペースまで移動
err = os.Chdir(workspaceFolder)
if err != nil {
return "", err
return "", &PsCommandError{msg: "Failed to change to workspace directory"}
}

dockerComposePsCommand := exec.Command("docker", "compose", "ps", "--format", "json")
Expand All @@ -37,11 +61,19 @@ func Ps(workspaceFolder string) (string, error) {
// `docker compose -p ${projectName} stop` を実行する。
func Stop(projectName string) error {
dockerComposeStopCommand := exec.Command("docker", "compose", "-p", projectName, "stop")
return dockerComposeStopCommand.Start()
err := dockerComposeStopCommand.Start()
if err != nil {
return &StopCommandError{msg: "Failed to execute docker compose stop command"}
}
return nil
}

// `docker compose -p ${projectName} down` を実行する。
func Down(projectName string) error {
dockerComposeDownCommand := exec.Command("docker", "compose", "-p", projectName, "down")
return dockerComposeDownCommand.Start()
err := dockerComposeDownCommand.Start()
if err != nil {
return &DownCommandError{msg: "Failed to execute docker compose down command"}
}
return nil
}
85 changes: 71 additions & 14 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
_ "embed"
"encoding/json"
"errors"
"fmt"
"os"
"path/filepath"
Expand Down Expand Up @@ -86,7 +87,8 @@ func main() {
if (!util.IsExists(vimrc)) {
err := util.CreateFileWithContents(vimrc, additionalVimrc, 0666)
if err != nil {
panic(err)
fmt.Fprintf(os.Stderr, "Error creating vimrc file: %v\n", err)
os.Exit(1)
}
fmt.Printf("Generated additional vimrc to: %s\n", vimrc)
}
Expand All @@ -97,7 +99,8 @@ func main() {
if (!util.IsExists(runargs)) {
err := util.CreateFileWithContents(runargs, runargsContent, 0666)
if err != nil {
panic(err)
fmt.Fprintf(os.Stderr, "Error creating runargs file: %v\n", err)
os.Exit(1)
}
fmt.Printf("Generated additional runargs to: %s\n", runargs)
}
Expand Down Expand Up @@ -315,14 +318,22 @@ func main() {
workspaceFolder := args[len(args)-1]
configFilePath, err := createConfigFile(devcontainerPath, workspaceFolder, configDirForDevcontainer)
if err != nil {
fmt.Fprintf(os.Stderr, "Error creating config file: %v\n", err)
if errors.Is(err, os.ErrNotExist) {
fmt.Fprintf(os.Stderr, "Configuration file not found: %v\n", err)
} else {
fmt.Fprintf(os.Stderr, "Error creating config file: %v\n", err)
}
os.Exit(1)
}

// devcontainer を用いたコンテナ立ち上げ
err = devcontainer.ExecuteDevcontainer(args, devcontainerPath, vimPath, cdrPath, configFilePath, vimrc)
if err != nil {
fmt.Fprintf(os.Stderr, "Error executing devcontainer: %v\n", err)
if errors.Is(err, os.ErrPermission) {
fmt.Fprintf(os.Stderr, "Permission error: %v\n", err)
} else {
fmt.Fprintf(os.Stderr, "Error executing devcontainer: %v\n", err)
}
os.Exit(1)
}

Expand All @@ -341,14 +352,22 @@ func main() {
// 必要なファイルのダウンロード
devcontainerPath, err := tools.InstallStopTools(binDir)
if err != nil {
fmt.Fprintf(os.Stderr, "Error installing stop tools: %v\n", err)
if errors.Is(err, os.ErrNotExist) {
fmt.Fprintf(os.Stderr, "Configuration file not found: %v\n", err)
} else {
fmt.Fprintf(os.Stderr, "Error installing stop tools: %v\n", err)
}
os.Exit(1)
}

// devcontainer を用いたコンテナ終了
err = devcontainer.Stop(cCtx.Args().Slice(), devcontainerPath, configDirForDevcontainer)
if err != nil {
fmt.Fprintf(os.Stderr, "Error stopping devcontainer: %v\n", err)
if errors.Is(err, os.ErrPermission) {
fmt.Fprintf(os.Stderr, "Permission error: %v\n", err)
} else {
fmt.Fprintf(os.Stderr, "Error stopping devcontainer: %v\n", err)
}
os.Exit(1)
}

Expand All @@ -369,14 +388,22 @@ func main() {
// 必要なファイルのダウンロード
devcontainerPath, err := tools.InstallDownTools(binDir)
if err != nil {
fmt.Fprintf(os.Stderr, "Error installing down tools: %v\n", err)
if errors.Is(err, os.ErrNotExist) {
fmt.Fprintf(os.Stderr, "Configuration file not found: %v\n", err)
} else {
fmt.Fprintf(os.Stderr, "Error installing down tools: %v\n", err)
}
os.Exit(1)
}

// devcontainer を用いたコンテナ終了
err = devcontainer.Down(cCtx.Args().Slice(), devcontainerPath, configDirForDevcontainer)
if err != nil {
fmt.Fprintf(os.Stderr, "Error downing devcontainer: %v\n", err)
if errors.Is(err, os.ErrPermission) {
fmt.Fprintf(os.Stderr, "Permission error: %v\n", err)
} else {
fmt.Fprintf(os.Stderr, "Error downing devcontainer: %v\n", err)
}
os.Exit(1)
}

Expand All @@ -389,7 +416,11 @@ func main() {
fmt.Printf("Remove configuration file: `%s`\n", configDir)
err = os.RemoveAll(configDir)
if err != nil {
fmt.Fprintf(os.Stderr, "Error removing configuration file: %v\n", err)
if errors.Is(err, os.ErrPermission) {
fmt.Fprintf(os.Stderr, "Permission error: %v\n", err)
} else {
fmt.Fprintf(os.Stderr, "Error removing configuration file: %v\n", err)
}
os.Exit(1)
}

Expand Down Expand Up @@ -665,12 +696,20 @@ func main() {
// 削除処理
err := os.RemoveAll(configDirForDocker)
if err != nil {
fmt.Fprintf(os.Stderr, "Error removing docker config directory: %v\n", err)
if errors.Is(err, os.ErrPermission) {
fmt.Fprintf(os.Stderr, "Permission error: %v\n", err)
} else {
fmt.Fprintf(os.Stderr, "Error removing docker config directory: %v\n", err)
}
os.Exit(1)
}
err = os.RemoveAll(configDirForDevcontainer)
if err != nil {
fmt.Fprintf(os.Stderr, "Error removing devcontainer config directory: %v\n", err)
if errors.Is(err, os.ErrPermission) {
fmt.Fprintf(os.Stderr, "Permission error: %v\n", err)
} else {
fmt.Fprintf(os.Stderr, "Error removing devcontainer config directory: %v\n", err)
}
os.Exit(1)
}

Expand All @@ -693,7 +732,11 @@ func main() {
// Features の一覧をダウンロード
err := oras.Pull("ghcr.io/devcontainers/index", "latest", appCacheDir)
if err != nil {
fmt.Fprintf(os.Stderr, "Error updating index: %v\n", err)
if errors.Is(err, os.ErrNotExist) {
fmt.Fprintf(os.Stderr, "Index file not found: %v\n", err)
} else {
fmt.Fprintf(os.Stderr, "Error updating index: %v\n", err)
}
os.Exit(1)
}

Expand All @@ -709,7 +752,11 @@ func main() {
Action: func(cCtx *cli.Context) error {
err := tools.SelfUpdate()
if err != nil {
fmt.Fprintf(os.Stderr, "Error updating devcontainer.vim: %v\n", err)
if errors.Is(err, os.ErrPermission) {
fmt.Fprintf(os.Stderr, "Permission error: %v\n", err)
} else {
fmt.Fprintf(os.Stderr, "Error updating devcontainer.vim: %v\n", err)
}
os.Exit(1)
}
return nil
Expand All @@ -730,7 +777,11 @@ func main() {
// アプリ実行
err := devcontainerVimArgProcess.Run(os.Args)
if err != nil {
fmt.Fprintf(os.Stderr, "Error running devcontainer.vim: %v\n", err)
if errors.Is(err, os.ErrPermission) {
fmt.Fprintf(os.Stderr, "Permission error: %v\n", err)
} else {
fmt.Fprintf(os.Stderr, "Error running devcontainer.vim: %v\n", err)
}
os.Exit(1)
}
}
Expand All @@ -742,6 +793,9 @@ func createConfigFile(devcontainerPath string, workspaceFolder string, configDir
// devcontainer の設定ファイルパス取得
configFilePath, err := devcontainer.GetConfigurationFilePath(devcontainerPath, workspaceFolder)
if err != nil {
if errors.Is(err, os.ErrNotExist) {
return "", fmt.Errorf("configuration file not found: %w", err)
}
return "", err
}

Expand All @@ -752,6 +806,9 @@ func createConfigFile(devcontainerPath string, workspaceFolder string, configDir
// 設定管理フォルダに JSON を配置
mergedConfigFilePath, err := util.CreateConfigFileForDevcontainer(configDirForDevcontainer, workspaceFolder, configFilePath, additionalConfigurationFilePath)
if err != nil {
if errors.Is(err, os.ErrPermission) {
return "", fmt.Errorf("permission error: %w", err)
}
return "", err
}

Expand Down

0 comments on commit 8c68e81

Please sign in to comment.