diff --git a/state/local.go b/state/local.go index e1129ebbe0..b34d048376 100644 --- a/state/local.go +++ b/state/local.go @@ -39,6 +39,10 @@ type LocalState struct { // the file handle corresponding to PathOut stateFileOut *os.File + // created is set to tru if stateFileOut didn't exist before we created it. + // This is mostly so we can clean up emtpy files during tests, but doesn't + // hurt to remove file we never wrote to. + created bool state *terraform.State readState *terraform.State @@ -75,8 +79,26 @@ func (s *LocalState) Lock(reason string) error { } func (s *LocalState) Unlock() error { + // we can't be locked if we don't have a file + if s.stateFileOut == nil { + return nil + } + os.Remove(s.lockInfoPath()) - return s.unlock() + + fileName := s.stateFileOut.Name() + + unlockErr := s.unlock() + s.stateFileOut.Close() + s.stateFileOut = nil + + // clean up the state file if we created it an never wrote to it + stat, err := os.Stat(fileName) + if err == nil && stat.Size() == 0 && s.created { + os.Remove(fileName) + } + + return unlockErr } // Open the state file, creating the directories and file as needed. @@ -85,28 +107,25 @@ func (s *LocalState) createStateFiles() error { s.PathOut = s.Path } - f, err := createFileAndDirs(s.PathOut) + // yes this could race, but we only use it to clean up empty files + if _, err := os.Stat(s.PathOut); os.IsNotExist(err) { + s.created = true + } + + // Create all the directories + if err := os.MkdirAll(filepath.Dir(s.PathOut), 0755); err != nil { + return err + } + + f, err := os.OpenFile(s.PathOut, os.O_RDWR|os.O_CREATE, 0666) if err != nil { return err } + s.stateFileOut = f return nil } -func createFileAndDirs(path string) (*os.File, error) { - // Create all the directories - if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil { - return nil, err - } - - f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0666) - if err != nil { - return nil, err - } - - return f, nil -} - // WriteState for LocalState always persists the state as well. // TODO: this should use a more robust method of writing state, by first // writing to a temp file on the same filesystem, and renaming the file over