Skip to content

Commit

Permalink
Add test reproducing vim backupcopy=no and kqueue failure (#139)
Browse files Browse the repository at this point in the history
* Add test reproducing vim backupcopy=no and kqueue failure

This test reproduces the write behavior of vim with `backupcopy` set to
both `yes` and `no`. `yes` is the default on Linux, and #10 fixed this
case. Unforunately, on macOS, `yes` is not the default, and using `no`
will cause ibazel to stop watching the file after a single file save
when a kqueue-based file watcher is used.

* Readd files when they are moved to overcome limitations in kqueue.
  • Loading branch information
clintharrison authored and achew22 committed Sep 30, 2018
1 parent 0586b88 commit 0a37513
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 3 deletions.
108 changes: 108 additions & 0 deletions e2e/simple/simple_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package simple

import (
"fmt"
"io"
"os"
"runtime/debug"
"testing"
Expand Down Expand Up @@ -106,3 +108,109 @@ sh_binary(
`))
ibazel.ExpectOutput("Started3!")
}

func renameAndWriteNewFile(t *testing.T, fname, content string) {
// write a file in the same manner as vim with backupcopy=no;
// this will rename the original file to a file with a backup extension
// and write the new file contents to the original filename

fnameBackup := fmt.Sprintf("%s~", fname)
must(t, os.Rename(fname, fnameBackup))
f, err := os.OpenFile(fname, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0777)
if err != nil {
t.Fatal(err)
}
_, err = f.Write([]byte(content))
if err != nil {
t.Fatal(err)
}
must(t, f.Close())
must(t, os.Remove(fnameBackup))
}

func copyAndTruncWriteFile(t *testing.T, fname string, content string) {
// write a file in the same manner as vim with backupcopy=yes;
// this will copy the file to a suffixed backup file,
// truncate the existing file and write the new content
fnameBackup := fmt.Sprintf("%s~", fname)

f, err := os.Open(fname)
if err != nil {
t.Fatal(err)
}
fBackup, err := os.OpenFile(fnameBackup, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
t.Fatal(err)
}

_, err = io.Copy(fBackup, f)
if err != nil {
t.Fatal(err)
}
must(t, fBackup.Close())
must(t, f.Close())

f, err = os.OpenFile(fname, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
t.Fatal(err)
}
_, err = f.Write([]byte(content))
if err != nil {
t.Fatal(err)
}
must(t, f.Sync())
must(t, f.Close())
must(t, os.Remove(fnameBackup))
}

func TestSimpleRunWithModifiedFile_RenameAndWrite(t *testing.T) {
b, err := bazel.New()
if err != nil {
t.Fatal(err)
}
must(t, b.ScratchFile("WORKSPACE", ""))
must(t, b.ScratchFileWithMode("test.sh", `printf "Started!"`, 0777))
must(t, b.ScratchFile("BUILD", `
sh_binary(
name = "test",
srcs = ["test.sh"],
)
`))

ibazel := e2e.NewIBazelTester(t, b)
ibazel.Run("//:test")
defer ibazel.Kill()
ibazel.ExpectOutput("Started!")

renameAndWriteNewFile(t, "test.sh", `printf "Started2!"`)
ibazel.ExpectOutput("Started2!")

renameAndWriteNewFile(t, "test.sh", `printf "Started3!"`)
ibazel.ExpectOutput("Started3!")
}

func TestSimpleRunWithModifiedFile_CopyAndTruncWrite(t *testing.T) {
b, err := bazel.New()
if err != nil {
t.Fatal(err)
}
must(t, b.ScratchFile("WORKSPACE", ""))
must(t, b.ScratchFileWithMode("test.sh", `printf "Started!"`, 0777))
must(t, b.ScratchFile("BUILD", `
sh_binary(
name = "test",
srcs = ["test.sh"],
)
`))

ibazel := e2e.NewIBazelTester(t, b)
ibazel.Run("//:test")
defer ibazel.Kill()
ibazel.ExpectOutput("Started!")

copyAndTruncWriteFile(t, "test.sh", `printf "Started2!"`)
ibazel.ExpectOutput("Started2!")

copyAndTruncWriteFile(t, "test.sh", `printf "Started3!"`)
ibazel.ExpectOutput("Started3!")
}
8 changes: 5 additions & 3 deletions ibazel/source_event_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@

package main

import "github.com/fsnotify/fsnotify"
import (
"github.com/fsnotify/fsnotify"
)

type SourceEventHandler struct {
SourceFileEvents chan fsnotify.Event
Expand All @@ -28,8 +30,8 @@ func (s *SourceEventHandler) Listen() {
s.SourceFileEvents <- event

switch event.Op {
case fsnotify.Remove:
s.SourceFileWatcher.Add(event.Name)
case fsnotify.Remove, fsnotify.Rename:
s.SourceFileWatcher.Add(event.Name)
}
}
}
Expand Down

0 comments on commit 0a37513

Please sign in to comment.