Skip to content

Commit

Permalink
Handle Windows long file names in a few more places.
Browse files Browse the repository at this point in the history
Go can handle long file names on Windows if they are not relative.
This change makes some file paths absolute so that go can handle them.
See https://github.com/golang/go/blob/b86e76681366447798c94abb959bb60875bcc856/src/os/path_windows.go#L133.

The protoc binary cannot handle long filenames either, so this change
generates go protos in the temporary folder and then moves the contents
into place.
  • Loading branch information
pmuetschard committed Mar 15, 2018
1 parent 67f4403 commit 8d52857
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 13 deletions.
1 change: 1 addition & 0 deletions go/tools/builders/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ go_tool_binary(
go_tool_binary(
name = "go-protoc",
srcs = [
"env.go",
"flags.go",
"protoc.go",
],
Expand Down
5 changes: 3 additions & 2 deletions go/tools/builders/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ func run(args []string) error {
if err := goenv.update(); err != nil {
return err
}
absOutput := abs(*output) // required to work with long paths on Windows

var matcher func(f *goMetadata) bool
switch *testfilter {
Expand Down Expand Up @@ -80,7 +81,7 @@ func run(args []string) error {
}
}
if len(files) <= 0 {
return ioutil.WriteFile(*output, []byte(""), 0644)
return ioutil.WriteFile(absOutput, []byte(""), 0644)
}

goargs := []string{"tool", "compile"}
Expand All @@ -102,7 +103,7 @@ func run(args []string) error {
goargs = append(goargs, "-importmap", mapping)
strictdeps = append(strictdeps, source)
}
goargs = append(goargs, "-pack", "-o", *output)
goargs = append(goargs, "-pack", "-o", absOutput)
goargs = append(goargs, flags.Args()...)
for _, f := range files {
goargs = append(goargs, f.filename)
Expand Down
4 changes: 4 additions & 0 deletions go/tools/builders/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ type GoEnv struct {
ld_flags multiFlag
}

// abs returns the absolute representation of path. Some tools/APIs require
// absolute paths to work correctly. Most notably, golang on Windows cannot
// handle relative paths to files whose absolute path is > ~250 chars, while
// it can handle absolute paths. See http://goo.gl/eqeWjm.
func abs(path string) string {
if abs, err := filepath.Abs(path); err != nil {
return path
Expand Down
2 changes: 1 addition & 1 deletion go/tools/builders/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ type goMetadata struct {
func readFiles(bctx build.Context, inputs []string) ([]*goMetadata, error) {
outputs := []*goMetadata{}
for _, input := range inputs {
if m, err := readGoMetadata(bctx, input, true); err != nil {
if m, err := readGoMetadata(bctx, abs(input), true); err != nil {
return nil, err
} else if m.matched {
outputs = append(outputs, m)
Expand Down
5 changes: 5 additions & 0 deletions go/tools/builders/filter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,8 @@ func runTest(t *testing.T, bctx build.Context, inputs []string, expect []string)
t.Errorf("filter %v,%v,%v,%v: expect %v got %v", bctx.GOOS, bctx.GOARCH, bctx.CgoEnabled, bctx.BuildTags, expect, got)
}
}

// abs is a dummy env.go abs to avoid depending on env.go and flags.go.
func abs(p string) string {
return p
}
49 changes: 39 additions & 10 deletions go/tools/builders/protoc.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,25 @@ func run(args []string) error {
if err := flags.Parse(args); err != nil {
return err
}

// Output to a temporary folder and then move the contents into place below.
// This is to work around long file paths on Windows.
tmpDir, err := ioutil.TempDir("", "go_proto")
if err != nil {
return err
}
tmpDir = abs(tmpDir) // required to work with long paths on Windows
absOutPath := abs(*outPath) // required to work with long paths on Windows
defer os.RemoveAll(tmpDir)

pluginBase := filepath.Base(*plugin)
pluginName := strings.TrimSuffix(
strings.TrimPrefix(filepath.Base(*plugin), "protoc-gen-"), ".exe")
for _, m := range imports {
options = append(options, fmt.Sprintf("M%v", m))
}
protoc_args := []string{
fmt.Sprintf("--%v_out=%v:%v", pluginName, strings.Join(options, ","), *outPath),
fmt.Sprintf("--%v_out=%v:%v", pluginName, strings.Join(options, ","), tmpDir),
"--plugin", fmt.Sprintf("%v=%v", strings.TrimSuffix(pluginBase, ".exe"), *plugin),
"--descriptor_set_in", strings.Join(descriptors, string(os.PathListSeparator)),
}
Expand Down Expand Up @@ -95,28 +106,45 @@ func run(args []string) error {
}
}
// Walk the generated files
filepath.Walk(*outPath, func(path string, f os.FileInfo, err error) error {
if !strings.HasSuffix(path, ".go") {
filepath.Walk(tmpDir, func(path string, f os.FileInfo, err error) error {
relPath, err := filepath.Rel(tmpDir, path)
if err != nil {
return err
}
if relPath == "." {
return nil
}
info := files[path]
if info != nil {
info.created = true

if f.IsDir() {
if err := os.Mkdir(filepath.Join(absOutPath, relPath), f.Mode()); !os.IsExist(err) {
return err
}
return nil
}
info = &genFileInfo{

if !strings.HasSuffix(path, ".go") {
return nil
}

info := &genFileInfo{
path: path,
base: filepath.Base(path),
created: true,
}
files[path] = info

if foundInfo, ok := files[relPath]; ok {
foundInfo.created = true
foundInfo.from = info
return nil
}
files[relPath] = info
copyTo := byBase[info.base]
switch {
case copyTo == nil:
// Unwanted output
case !copyTo.unique:
// not unique, no copy allowed
case info.from != nil:
case copyTo.from != nil:
copyTo.ambiguious = true
info.ambiguious = true
default:
Expand All @@ -138,7 +166,7 @@ func run(args []string) error {
if err != nil {
return err
}
if err := ioutil.WriteFile(f.path, data, 0644); err != nil {
if err := ioutil.WriteFile(abs(f.path), data, 0644); err != nil {
return err
}
case !f.expected:
Expand All @@ -149,6 +177,7 @@ func run(args []string) error {
return errors.New(buf.String())
}
}

return nil
}

Expand Down

0 comments on commit 8d52857

Please sign in to comment.