Skip to content

Commit 0bf2eb5

Browse files
author
Jay Conrod
committed
cmd/go/internal/modfetch: switch to golang.org/x/mod/zip
zip.Create is now used to filter and translate zip files from VCS tools. zip.Unzip is now used instead of Unzip. Fixes #35290 Change-Id: I4aa41b2e96bf147c09db43d1d189b8393cafb06f Reviewed-on: https://go-review.googlesource.com/c/go/+/204917 Run-TryBot: Jay Conrod <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Bryan C. Mills <[email protected]>
1 parent 947f850 commit 0bf2eb5

File tree

6 files changed

+640
-259
lines changed

6 files changed

+640
-259
lines changed

src/cmd/go.sum

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ golang.org/x/arch v0.0.0-20190815191158-8a70ba74b3a1/go.mod h1:flIaEI6LNU6xOCD5P
77
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
88
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
99
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
10-
golang.org/x/mod v0.1.1-0.20191101203923-a222b9651630 h1:QsMqsRXZFQT+jRZnwpEDIwGHWg0UY9ZrpWiplCOEK5I=
11-
golang.org/x/mod v0.1.1-0.20191101203923-a222b9651630/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
1210
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee h1:WG0RUwxtNT4qqaXX3DPA8zHFNm/D9xaBpxzHt1WcA/E=
1311
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
1412
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=

src/cmd/go/internal/modfetch/coderepo.go

Lines changed: 38 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package modfetch
66

77
import (
88
"archive/zip"
9+
"bytes"
910
"errors"
1011
"fmt"
1112
"io"
@@ -21,6 +22,7 @@ import (
2122
"golang.org/x/mod/modfile"
2223
"golang.org/x/mod/module"
2324
"golang.org/x/mod/semver"
25+
modzip "golang.org/x/mod/zip"
2426
)
2527

2628
// A codeRepo implements modfetch.Repo using an underlying codehost.Repo.
@@ -900,13 +902,12 @@ func (r *codeRepo) Zip(dst io.Writer, version string) error {
900902
return err
901903
}
902904

903-
zw := zip.NewWriter(dst)
905+
var files []modzip.File
904906
if subdir != "" {
905907
subdir += "/"
906908
}
907909
haveLICENSE := false
908910
topPrefix := ""
909-
haveGoMod := make(map[string]bool)
910911
for _, zf := range zr.File {
911912
if topPrefix == "" {
912913
i := strings.Index(zf.Name, "/")
@@ -918,106 +919,61 @@ func (r *codeRepo) Zip(dst io.Writer, version string) error {
918919
if !strings.HasPrefix(zf.Name, topPrefix) {
919920
return fmt.Errorf("zip file contains more than one top-level directory")
920921
}
921-
dir, file := path.Split(zf.Name)
922-
if file == "go.mod" {
923-
haveGoMod[dir] = true
924-
}
925-
}
926-
root := topPrefix + subdir
927-
inSubmodule := func(name string) bool {
928-
for {
929-
dir, _ := path.Split(name)
930-
if len(dir) <= len(root) {
931-
return false
932-
}
933-
if haveGoMod[dir] {
934-
return true
935-
}
936-
name = dir[:len(dir)-1]
937-
}
938-
}
939-
940-
for _, zf := range zr.File {
941-
if !zf.FileInfo().Mode().IsRegular() {
942-
// Skip symlinks (golang.org/issue/27093).
943-
continue
944-
}
945-
946-
if topPrefix == "" {
947-
i := strings.Index(zf.Name, "/")
948-
if i < 0 {
949-
return fmt.Errorf("missing top-level directory prefix")
950-
}
951-
topPrefix = zf.Name[:i+1]
952-
}
953-
if strings.HasSuffix(zf.Name, "/") { // drop directory dummy entries
954-
continue
955-
}
956-
if !strings.HasPrefix(zf.Name, topPrefix) {
957-
return fmt.Errorf("zip file contains more than one top-level directory")
958-
}
959922
name := strings.TrimPrefix(zf.Name, topPrefix)
960923
if !strings.HasPrefix(name, subdir) {
961924
continue
962925
}
963-
if name == ".hg_archival.txt" {
964-
// Inserted by hg archive.
965-
// Not correct to drop from other version control systems, but too bad.
966-
continue
967-
}
968926
name = strings.TrimPrefix(name, subdir)
969-
if isVendoredPackage(name) {
927+
if name == "" || strings.HasSuffix(name, "/") {
970928
continue
971929
}
972-
if inSubmodule(zf.Name) {
973-
continue
974-
}
975-
base := path.Base(name)
976-
if strings.ToLower(base) == "go.mod" && base != "go.mod" {
977-
return fmt.Errorf("zip file contains %s, want all lower-case go.mod", zf.Name)
978-
}
930+
files = append(files, zipFile{name: name, f: zf})
979931
if name == "LICENSE" {
980932
haveLICENSE = true
981933
}
982-
size := int64(zf.UncompressedSize64)
983-
if size < 0 || maxSize < size {
984-
return fmt.Errorf("module source tree too big")
985-
}
986-
maxSize -= size
987-
988-
rc, err := zf.Open()
989-
if err != nil {
990-
return err
991-
}
992-
w, err := zw.Create(r.modPrefix(version) + "/" + name)
993-
if err != nil {
994-
return err
995-
}
996-
lr := &io.LimitedReader{R: rc, N: size + 1}
997-
if _, err := io.Copy(w, lr); err != nil {
998-
return err
999-
}
1000-
if lr.N <= 0 {
1001-
return fmt.Errorf("individual file too large")
1002-
}
1003934
}
1004935

1005936
if !haveLICENSE && subdir != "" {
1006937
data, err := r.code.ReadFile(rev, "LICENSE", codehost.MaxLICENSE)
1007938
if err == nil {
1008-
w, err := zw.Create(r.modPrefix(version) + "/LICENSE")
1009-
if err != nil {
1010-
return err
1011-
}
1012-
if _, err := w.Write(data); err != nil {
1013-
return err
1014-
}
939+
files = append(files, dataFile{name: "LICENSE", data: data})
1015940
}
1016941
}
1017942

1018-
return zw.Close()
943+
return modzip.Create(dst, module.Version{Path: r.modPath, Version: version}, files)
944+
}
945+
946+
type zipFile struct {
947+
name string
948+
f *zip.File
949+
}
950+
951+
func (f zipFile) Path() string { return f.name }
952+
func (f zipFile) Lstat() (os.FileInfo, error) { return f.f.FileInfo(), nil }
953+
func (f zipFile) Open() (io.ReadCloser, error) { return f.f.Open() }
954+
955+
type dataFile struct {
956+
name string
957+
data []byte
958+
}
959+
960+
func (f dataFile) Path() string { return f.name }
961+
func (f dataFile) Lstat() (os.FileInfo, error) { return dataFileInfo{f}, nil }
962+
func (f dataFile) Open() (io.ReadCloser, error) {
963+
return ioutil.NopCloser(bytes.NewReader(f.data)), nil
1019964
}
1020965

966+
type dataFileInfo struct {
967+
f dataFile
968+
}
969+
970+
func (fi dataFileInfo) Name() string { return path.Base(fi.f.name) }
971+
func (fi dataFileInfo) Size() int64 { return int64(len(fi.f.data)) }
972+
func (fi dataFileInfo) Mode() os.FileMode { return 0644 }
973+
func (fi dataFileInfo) ModTime() time.Time { return time.Time{} }
974+
func (fi dataFileInfo) IsDir() bool { return false }
975+
func (fi dataFileInfo) Sys() interface{} { return nil }
976+
1021977
// hasPathPrefix reports whether the path s begins with the
1022978
// elements in prefix.
1023979
func hasPathPrefix(s, prefix string) bool {

src/cmd/go/internal/modfetch/fetch.go

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525

2626
"golang.org/x/mod/module"
2727
"golang.org/x/mod/sumdb/dirhash"
28+
modzip "golang.org/x/mod/zip"
2829
)
2930

3031
var downloadCache par.Cache
@@ -113,8 +114,7 @@ func download(mod module.Version, dir string) (err error) {
113114
}
114115
}()
115116

116-
modpath := mod.Path + "@" + mod.Version
117-
if err := Unzip(tmpDir, zipfile, modpath, 0); err != nil {
117+
if err := modzip.Unzip(tmpDir, mod, zipfile); err != nil {
118118
fmt.Fprintf(os.Stderr, "-> %s\n", err)
119119
return err
120120
}
@@ -266,6 +266,45 @@ func downloadZip(mod module.Version, zipfile string) (err error) {
266266
return nil
267267
}
268268

269+
// makeDirsReadOnly makes a best-effort attempt to remove write permissions for dir
270+
// and its transitive contents.
271+
func makeDirsReadOnly(dir string) {
272+
type pathMode struct {
273+
path string
274+
mode os.FileMode
275+
}
276+
var dirs []pathMode // in lexical order
277+
filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
278+
if err == nil && info.Mode()&0222 != 0 {
279+
if info.IsDir() {
280+
dirs = append(dirs, pathMode{path, info.Mode()})
281+
}
282+
}
283+
return nil
284+
})
285+
286+
// Run over list backward to chmod children before parents.
287+
for i := len(dirs) - 1; i >= 0; i-- {
288+
os.Chmod(dirs[i].path, dirs[i].mode&^0222)
289+
}
290+
}
291+
292+
// RemoveAll removes a directory written by Download or Unzip, first applying
293+
// any permission changes needed to do so.
294+
func RemoveAll(dir string) error {
295+
// Module cache has 0555 directories; make them writable in order to remove content.
296+
filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
297+
if err != nil {
298+
return nil // ignore errors walking in file system
299+
}
300+
if info.IsDir() {
301+
os.Chmod(path, 0777)
302+
}
303+
return nil
304+
})
305+
return os.RemoveAll(dir)
306+
}
307+
269308
var GoSumFile string // path to go.sum; set by package modload
270309

271310
type modSum struct {

0 commit comments

Comments
 (0)