package main

import (
	
	
	
	
	
	
)

type workspace struct {
	// Dir, if non-empty, is a directory of the Go workspace.
	Dir string
	// Paths is a list of modules in the current workspace. If Dir is empty,
	// it contains a single directory for the main module.
	Paths []string
}

// Root returns workspace root directory.
func ( *workspace) () string {
	if .Dir == "" {
		return .Paths[0]
	}
	return .Dir
}

func () (*workspace, error) {
	,  := goenv("GOMOD", "GOWORK")
	if  != nil {
		return nil, 
	}

	,  := ["GOWORK"]
	if ! ||  == "" ||  == "off" {
		,  := ["GOMOD"]
		if ! ||  == "" ||  == os.DevNull {
			return nil, errors.New("no go.work or go.mod files found")
		}
		return &workspace{
			Paths: []string{
				filepath.Dir(),
			},
		}, nil
	}

	 := filepath.Dir()

	var  bytes.Buffer
	 := exec.Command("go", "work", "edit", "-json")
	.Stdout = &
	.Stderr = os.Stderr
	.Dir = 
	if  := .Run();  != nil {
		return nil, 
	}
	var  struct {
		 []struct {
			 string
		}
	}
	if  := json.Unmarshal(.Bytes(), &);  != nil {
		return nil, 
	}

	 := make([]string, len(.))
	for ,  := range . {
		[] = filepath.Join(, filepath.FromSlash(.))
	}
	return &workspace{
		Dir:   ,
		Paths: ,
	}, nil
}

// syncWorkspace runs go mod tidy and go work sync for the given workspace.
func ( *workspace) error {
	for ,  := range .Paths {
		 := exec.Command("go", "mod", "tidy")
		.Stderr = os.Stderr
		.Dir = 
		if  := .Run();  != nil {
			return 
		}
	}
	return goworksync()
}

// goworksync removes current go.work.sum file and runs go work sync.
func ( *workspace) error {
	if .Dir == "" {
		return nil
	}
	if  := os.Remove(filepath.Join(.Dir, "go.work.sum"));  != nil && !os.IsNotExist() {
		return 
	}
	 := exec.Command("go", "work", "sync")
	.Stderr = os.Stderr
	.Dir = .Dir
	return .Run()
}

// goenv returns the given Go environment variables.
func ( ...string) (map[string]string, error) {
	var  bytes.Buffer
	 := exec.Command("go", append([]string{"env", "-json", "--"}, ...)...)
	.Stdout = &
	.Stderr = os.Stderr
	if  := .Run();  != nil {
		return nil, 
	}
	 := make(map[string]string)
	if  := json.Unmarshal(.Bytes(), &);  != nil {
		return nil, 
	}
	return , nil
}