9
9
"errors"
10
10
"fmt"
11
11
"io/fs"
12
+ "os"
12
13
"path"
13
14
"strings"
14
15
@@ -21,60 +22,101 @@ import (
21
22
func extractReadmes (modulePath , resolvedVersion string , contentDir fs.FS ) (_ []* internal.Readme , err error ) {
22
23
defer derrors .Wrap (& err , "extractReadmes(ctx, %q, %q, r)" , modulePath , resolvedVersion )
23
24
24
- // The key is the README directory. Since we only store one README file per
25
- // directory, we use this below to prioritize READMEs in markdown.
26
- readmes := map [string ]* internal.Readme {}
27
- var skipPaths = []string {"_" }
25
+ var readmes []* internal.Readme
28
26
err = fs .WalkDir (contentDir , "." , func (pathname string , d fs.DirEntry , err error ) error {
29
27
if err != nil {
30
28
return err
31
29
}
32
- for _ , sp := range skipPaths {
33
- // if the name of the folder has a prefix listed in skipPaths
34
- // then we should skip the directory.
35
- // e.g. _foo
36
- if strings .HasPrefix (pathname , sp ) {
37
- return fs .SkipDir
38
- }
30
+
31
+ if ! d .IsDir () {
32
+ return nil
33
+ }
34
+
35
+ readme , err := extractReadme (modulePath , path .Join (modulePath , pathname ), resolvedVersion , contentDir )
36
+ if err != nil {
37
+ return err
39
38
}
39
+ if readme == nil {
40
+ // no readme for the directory
41
+ return nil
42
+ }
43
+ readmes = append (readmes , readme )
44
+ return nil
45
+ })
46
+ if err != nil && ! errors .Is (err , fs .ErrNotExist ) { // we can get NotExist on an empty FS {
47
+ return nil , err
48
+ }
49
+ return readmes , nil
50
+ }
51
+
52
+ // rel returns the relative path from the modulePath to the pkgPath
53
+ // returning "." if they're the same.
54
+ func rel (pkgPath , modulePath string ) string {
55
+ suff := internal .Suffix (pkgPath , modulePath )
56
+ if suff == "" {
57
+ return "."
58
+ }
59
+ return suff
60
+ }
61
+
62
+ // extractReadme returns the file path and contents the unit's README,
63
+ // if there is one. dir is the directory path prefixed with the modulePath.
64
+ func extractReadme (modulePath , dir , resolvedVersion string , contentDir fs.FS ) (_ * internal.Readme , err error ) {
65
+ defer derrors .Wrap (& err , "extractReadme(ctx, %q, %q %q, r)" , modulePath , dir , resolvedVersion )
66
+
67
+ innerPath := rel (dir , modulePath )
68
+ if strings .HasPrefix (innerPath , "_" ) {
69
+ // TODO(matloob): do we want to check each element of the path?
70
+ // The original code didn't.
71
+ return nil , nil
72
+ }
40
73
41
- if ! d .IsDir () && isReadme (pathname ) {
42
- info , err := d .Info ()
74
+ f , err := contentDir .Open (innerPath )
75
+ if err != nil {
76
+ if os .IsNotExist (err ) {
77
+ return nil , nil
78
+ }
79
+ return nil , err
80
+ }
81
+ rdf , ok := f .(fs.ReadDirFile )
82
+ if ! ok {
83
+ return nil , fmt .Errorf ("could not open directory for %v" , dir )
84
+ }
85
+ entries , err := rdf .ReadDir (0 )
86
+ if err != nil {
87
+ return nil , err
88
+ }
89
+ var readme * internal.Readme
90
+ for _ , e := range entries {
91
+ pathname := path .Join (innerPath , e .Name ())
92
+ if ! e .IsDir () && isReadme (pathname ) {
93
+ info , err := e .Info ()
43
94
if err != nil {
44
- return err
95
+ return nil , err
45
96
}
46
97
if info .Size () > MaxFileSize {
47
- return fmt .Errorf ("file size %d exceeds max limit %d: %w" , info .Size (), MaxFileSize , derrors .ModuleTooLarge )
98
+ return nil , fmt .Errorf ("file size %d exceeds max limit %d: %w" , info .Size (), MaxFileSize , derrors .ModuleTooLarge )
48
99
}
49
100
c , err := readFSFile (contentDir , pathname , MaxFileSize )
50
101
if err != nil {
51
- return err
102
+ return nil , err
52
103
}
53
104
54
- key := path .Dir (pathname )
55
- if r , ok := readmes [key ]; ok {
105
+ if readme != nil {
56
106
// Prefer READMEs written in markdown, since we style these on
57
107
// the frontend.
58
- ext := path .Ext (r .Filepath )
108
+ ext := path .Ext (readme .Filepath )
59
109
if ext == ".md" || ext == ".markdown" {
60
- return nil
110
+ continue
61
111
}
62
112
}
63
- readmes [ key ] = & internal.Readme {
113
+ readme = & internal.Readme {
64
114
Filepath : pathname ,
65
115
Contents : string (c ),
66
116
}
67
117
}
68
- return nil
69
- })
70
- if err != nil && ! errors .Is (err , fs .ErrNotExist ) { // we can get NotExist on an empty FS {
71
- return nil , err
72
- }
73
- var rs []* internal.Readme
74
- for _ , r := range readmes {
75
- rs = append (rs , r )
76
118
}
77
- return rs , nil
119
+ return readme , nil
78
120
}
79
121
80
122
var excludedReadmeExts = map [string ]bool {".go" : true , ".vendor" : true }
0 commit comments