Skip to content
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
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -186,4 +186,4 @@ jobs:

- name: "verify used"
run: |
go test -v ./testing/ci '-verify-used'
go test -v ./testing/ci '-verify-used' '-relative-open'
35 changes: 34 additions & 1 deletion testing/ci/ci_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,48 @@
package ci

import (
"bytes"
"encoding/json"
"flag"
"net/http"
"os"
"path/filepath"
"testing"

"github.com/tailscale/gomodfs"
)

var runVerifyUsed = flag.Bool("verify-used", false, "if set, runs TestVerifyUsed")
var (
runVerifyUsed = flag.Bool("verify-used", false, "if set, runs TestVerifyUsed")
runRelativeOpen = flag.Bool("relative-open", false, "if set, runs TestRelativeOpen against the mounted $GOMODCACHE")
)

// TestRelativeOpen opens files in the mounted module cache by paths relative
// to a working directory on the mount, as cmd/asm does with #include files.
// On Windows, WinFsp used to pass such opens to gomodfs with the working
// directory's path upcased, because gomodfs's volume claimed to be
// case-insensitive and not case-preserving.
func TestRelativeOpen(t *testing.T) {
if !*runRelativeOpen {
t.Skip("only runs in CI with --relative-open set")
}
modCache := os.Getenv("GOMODCACHE")
if modCache == "" {
t.Fatal("GOMODCACHE not set")
}
t.Chdir(filepath.Join(modCache, "golang.org", "x", "sys@v0.16.0"))

b, err := os.ReadFile("go.mod")
if err != nil {
t.Fatalf("reading go.mod relative to the module dir: %v", err)
}
if !bytes.Contains(b, []byte("module golang.org/x/sys")) {
t.Errorf("go.mod contents = %q; want the golang.org/x/sys module", b)
}
if _, err := os.Stat("no-such-file"); !os.IsNotExist(err) {
t.Errorf("Stat of a missing relative path: err = %v; want not exist", err)
}
}

func TestVerifyUsed(t *testing.T) {
if !*runVerifyUsed {
Expand Down
8 changes: 7 additions & 1 deletion winfsp.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,13 @@ func (mfs *FS) MountWinFSP(mntPoint string) (MountRunner, error) {
},
mntPoint, // e.g. "M:"
winfsp.FileSystemName("gomodfs"),
winfsp.Attributes(winfsp.FspFSAttributeReadOnlyVolume),
// gomodfs paths are case-sensitive, like the GOMODCACHE layout it
// emulates (which escapes capitals as "!x"). Say so: on a volume
// that claims to be case-insensitive and not case-preserving,
// Windows passes relative opens to us with the working directory's
// path upcased, which we don't recognize.
winfsp.CaseSensitive(true),
winfsp.Attributes(winfsp.FspFSAttributeReadOnlyVolume|winfsp.FspFSAttributeCasePreservedNames),
)
if err != nil {
return nil, fmt.Errorf("winfsp.Mount: %w", err)
Expand Down
Loading