@@ -6,6 +6,7 @@ package modfetch
6
6
7
7
import (
8
8
"archive/zip"
9
+ "bytes"
9
10
"errors"
10
11
"fmt"
11
12
"io"
@@ -21,6 +22,7 @@ import (
21
22
"golang.org/x/mod/modfile"
22
23
"golang.org/x/mod/module"
23
24
"golang.org/x/mod/semver"
25
+ modzip "golang.org/x/mod/zip"
24
26
)
25
27
26
28
// A codeRepo implements modfetch.Repo using an underlying codehost.Repo.
@@ -900,13 +902,12 @@ func (r *codeRepo) Zip(dst io.Writer, version string) error {
900
902
return err
901
903
}
902
904
903
- zw := zip . NewWriter ( dst )
905
+ var files []modzip. File
904
906
if subdir != "" {
905
907
subdir += "/"
906
908
}
907
909
haveLICENSE := false
908
910
topPrefix := ""
909
- haveGoMod := make (map [string ]bool )
910
911
for _ , zf := range zr .File {
911
912
if topPrefix == "" {
912
913
i := strings .Index (zf .Name , "/" )
@@ -918,106 +919,61 @@ func (r *codeRepo) Zip(dst io.Writer, version string) error {
918
919
if ! strings .HasPrefix (zf .Name , topPrefix ) {
919
920
return fmt .Errorf ("zip file contains more than one top-level directory" )
920
921
}
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
- }
959
922
name := strings .TrimPrefix (zf .Name , topPrefix )
960
923
if ! strings .HasPrefix (name , subdir ) {
961
924
continue
962
925
}
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
- }
968
926
name = strings .TrimPrefix (name , subdir )
969
- if isVendoredPackage (name ) {
927
+ if name == "" || strings . HasSuffix (name , "/" ) {
970
928
continue
971
929
}
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 })
979
931
if name == "LICENSE" {
980
932
haveLICENSE = true
981
933
}
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
- }
1003
934
}
1004
935
1005
936
if ! haveLICENSE && subdir != "" {
1006
937
data , err := r .code .ReadFile (rev , "LICENSE" , codehost .MaxLICENSE )
1007
938
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 })
1015
940
}
1016
941
}
1017
942
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
1019
964
}
1020
965
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
+
1021
977
// hasPathPrefix reports whether the path s begins with the
1022
978
// elements in prefix.
1023
979
func hasPathPrefix (s , prefix string ) bool {
0 commit comments