Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove active workdir on prune #38

Merged
merged 2 commits into from
Jun 7, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions cmd/sourced/cmd/prune.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
)

type pruneCmd struct {
Command `name:"prune" short-description:"Stop and remove containers and resources" long-description:"Stops containers and removes containers, networks, and volumes created by 'init' for the current working directory.\nTo delete resources for all working directories pass --all flag.\nImages are not deleted unless you specify the --images flag."`
Command `name:"prune" short-description:"Stop and remove containers and resources" long-description:"Stops containers and removes containers, networks, volumes and configuration created by 'init' for the current working directory.\nTo delete resources for all working directories pass --all flag.\nImages are not deleted unless you specify the --images flag."`

All bool `short:"a" long:"all" description:"Remove containers and resources for all working directories"`
Images bool `long:"images" description:"Remove docker images"`
Expand Down Expand Up @@ -43,7 +43,20 @@ func (c *pruneCmd) pruneActive() error {
a = append(a, "--rmi", "all")
}

return compose.Run(context.Background(), a...)
if err := compose.Run(context.Background(), a...); err != nil {
return err
}

dir, err := workdir.Active()
if err != nil {
return err
}

if err := workdir.Remove(dir); err != nil {
return err
}

return workdir.UnsetActive()
}

func init() {
Expand Down
7 changes: 2 additions & 5 deletions cmd/sourced/cmd/workdirs.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,8 @@ func (c *workdirsCmd) Execute(args []string) error {
return err
}

active, err := workdir.ActiveRepoDir()
if err != nil {
return err
}

// ignore errors if active dir doesn't exist or unavailable
active, _ := workdir.ActiveRepoDir()
for _, dir := range dirs {
if dir == active {
fmt.Printf("* %s\n", dir)
Expand Down
83 changes: 73 additions & 10 deletions cmd/sourced/compose/workdir/workdir.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ import (

const activeDir = "__active__"

// RequiredFiles list of required files in a directory to treat it as a working directory
var RequiredFiles = []string{".env", "docker-compose.yml"}

// Init creates a working directory in ~/.srcd for the given repositories
// directory. The working directory will contain a docker-compose.yml and a
// .env file.
Expand Down Expand Up @@ -124,22 +127,46 @@ func SetActive(reposdir string) error {
return os.Symlink(workdir, dir)
}

// UnsetActive removes symlink for active workdir
func UnsetActive() error {
dir, err := Active()
if err != nil {
return err
}

_, err = os.Stat(dir)
if !os.IsNotExist(err) {
err = os.Remove(dir)
if err != nil {
return errors.Wrap(err, "could not delete active workdir directory symlink")
}
}

return nil
}

// Active returns the absolute path to $HOME/.srcd/workdirs/__active__
func Active() (string, error) {
return path(activeDir)
}

// ActiveRepoDir return repositories directory for an active working directory
func ActiveRepoDir() (string, error) {
wpath, err := workdirsPath()
// EvalActive returns resolved path to $HOME/.srcd/workdirs/__active__
func EvalActive() (string, error) {
active, err := Active()
if err != nil {
return "", err
}
active, err := Active()

return filepath.EvalSymlinks(active)
}

// ActiveRepoDir return repositories directory for an active working directory
func ActiveRepoDir() (string, error) {
wpath, err := workdirsPath()
if err != nil {
return "", err
}
active, err = filepath.EvalSymlinks(active)
active, err := EvalActive()
if err != nil {
return "", err
}
Expand All @@ -162,11 +189,13 @@ func List() ([]string, error) {
if info.IsDir() {
return nil
}
if info.Name() == ".env" || info.Name() == "docker-compose.yml" {
if _, ok := dirs[filepath.Dir(path)]; !ok {
dirs[filepath.Dir(path)] = 0
for _, f := range RequiredFiles {
if info.Name() == f {
if _, ok := dirs[filepath.Dir(path)]; !ok {
dirs[filepath.Dir(path)] = 0
}
dirs[filepath.Dir(path)]++
}
dirs[filepath.Dir(path)]++
}
return nil
})
Expand All @@ -176,7 +205,7 @@ func List() ([]string, error) {

res := make([]string, 0)
for dir, files := range dirs {
if files != 2 {
if files != len(RequiredFiles) {
continue
}
res = append(res, dir)
Expand Down Expand Up @@ -243,3 +272,37 @@ func stripBase(base, target string) (string, error) {

return filepath.Join("/", p), nil
}

// Remove removes working directory by removing required files
// and recursively removes directories up to the workdirs root as long as they are empty
func Remove(path string) error {
workdirsRoot, err := workdirsPath()
if err != nil {
return err
}

for _, f := range RequiredFiles {
if err := os.Remove(filepath.Join(path, f)); err != nil {
return errors.Wrap(err, "could not remove from workdir directory")
}
}

for {
files, err := ioutil.ReadDir(path)
if err != nil {
return errors.Wrap(err, "could not read workdir directory")
}
if len(files) > 0 {
Copy link
Contributor

@dpordomingo dpordomingo Jun 10, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if there's a .DS_Store here?
Why not checking there's no RequiredFiles?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what if there is super_import_file_dont_delete_me_or_I_will_loose_1_billion_dollars?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if I understood properly (from prev conversation), that file should not be there, so it would be reasonable to delete it, wouldn't it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as .DS_Store shouldn't be there. But it can be. Better play safe.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understood that sourced will ignore user changes on workdirs, not trying to keep them when pruning, but ok 👍

return nil
}

if err := os.Remove(path); err != nil {
return errors.Wrap(err, "could not delete workdir directory")
}

path = filepath.Dir(path)
if path == workdirsRoot {
return nil
}
}
}