@@ -2,157 +2,88 @@ package k6deps
2
2
3
3
import (
4
4
"archive/tar"
5
+ "bytes"
5
6
"encoding/json"
6
7
"errors"
7
8
"io"
8
- "os"
9
9
"path/filepath"
10
- "strings"
11
-
12
- "github.com/grafana/k6pack"
10
+ "slices"
13
11
)
14
12
15
- //nolint:forbidigo
16
- func loadMetadata (dir string , opts * Options ) error {
17
- var meta archiveMetadata
18
-
19
- data , err := os .ReadFile (filepath .Join (filepath .Clean (dir ), "metadata.json" ))
20
- if err != nil {
21
- return err
22
- }
23
-
24
- if err = json .Unmarshal (data , & meta ); err != nil {
25
- return err
26
- }
27
-
28
- opts .Manifest .Ignore = true // no manifest (yet) in archive
29
-
30
- opts .Script .Name = filepath .Join (
31
- dir ,
32
- "file" ,
33
- filepath .FromSlash (strings .TrimPrefix (meta .Filename , "file:///" )),
34
- )
35
-
36
- if value , found := meta .Env [EnvDependencies ]; found {
37
- opts .Env .Name = EnvDependencies
38
- opts .Env .Contents = []byte (value )
39
- } else {
40
- opts .Env .Ignore = true
41
- }
42
-
43
- contents , err := os .ReadFile (opts .Script .Name )
44
- if err != nil {
45
- return err
46
- }
47
-
48
- script , _ , err := k6pack .Pack (string (contents ), & k6pack.Options {Filename : opts .Script .Name })
49
- if err != nil {
50
- return err
51
- }
52
-
53
- opts .Script .Contents = script
54
-
55
- return nil
56
- }
57
-
58
13
type archiveMetadata struct {
59
14
Filename string `json:"filename"`
60
15
Env map [string ]string `json:"env"`
61
16
}
62
17
63
18
const maxFileSize = 1024 * 1024 * 10 // 10M
64
19
65
- //nolint:forbidigo
66
- func extractArchive (dir string , input io.Reader ) error {
20
+ func processArchive (input io.Reader ) (analyzer , error ) {
67
21
reader := tar .NewReader (input )
68
22
23
+ analyzers := make ([]analyzer , 0 )
24
+
69
25
for {
70
26
header , err := reader .Next ()
71
27
72
28
switch {
73
- case err == io .EOF :
74
- return nil
29
+ case errors . Is ( err , io .EOF ) :
30
+ return mergeAnalyzers ( analyzers ... ), nil
75
31
case err != nil :
76
- return err
32
+ return nil , err
77
33
case header == nil :
78
34
continue
79
35
}
80
36
81
- target := filepath .Join (dir , filepath .Clean (filepath .FromSlash (header .Name )))
82
-
83
- switch header .Typeflag {
84
- case tar .TypeDir :
85
- if err := os .MkdirAll (target , 0o750 ); err != nil {
86
- return err
87
- }
37
+ if header .Typeflag != tar .TypeReg || ! shouldProcess (header .Name ) {
38
+ continue
39
+ }
88
40
89
- case tar . TypeReg :
90
- if shouldSkip ( target ) {
91
- continue
92
- }
41
+ content := & bytes. Buffer {}
42
+ if _ , err := io . CopyN ( content , reader , maxFileSize ); err != nil && ! errors . Is ( err , io . EOF ) {
43
+ return nil , err
44
+ }
93
45
94
- file , err := os .OpenFile (filepath .Clean (target ), os .O_CREATE | os .O_RDWR , os .FileMode (header .Mode )) //nolint:gosec
46
+ // if the file is metadata.json, we extract the dependencies from the env
47
+ if header .Name == "metadata.json" {
48
+ analyzer , err := analizeMetadata (content .Bytes ())
95
49
if err != nil {
96
- return err
97
- }
98
-
99
- if _ , err := io .CopyN (file , reader , maxFileSize ); err != nil && ! errors .Is (err , io .EOF ) {
100
- return err
101
- }
102
-
103
- if err = file .Close (); err != nil {
104
- return err
105
- }
106
-
107
- // if it is a link or symlink, we copy the content of the linked file to the target
108
- // we assume the linked file was already processed and exists in the directory.
109
- case tar .TypeLink , tar .TypeSymlink :
110
- if shouldSkip (target ) {
111
- continue
50
+ return nil , err
112
51
}
52
+ analyzers = append (analyzers , analyzer )
53
+ continue
54
+ }
113
55
114
- linkedFile := filepath .Join (dir , filepath .Clean (filepath .FromSlash (header .Linkname )))
115
- if err := followLink (linkedFile , target ); err != nil {
116
- return err
117
- }
56
+ // analize the file content as an script
57
+ target := filepath .Clean (filepath .FromSlash (header .Name ))
58
+ src := Source {
59
+ Name : target ,
60
+ Contents : content .Bytes (),
118
61
}
62
+
63
+ analyzers = append (analyzers , scriptAnalyzer (src ))
119
64
}
120
65
}
121
66
122
- // indicates if the file should be skipped during extraction
123
- // we skip csv files and .json except metadata.json
124
- func shouldSkip (target string ) bool {
67
+ // indicates if the file should be processed during extraction
68
+ func shouldProcess (target string ) bool {
125
69
ext := filepath .Ext (target )
126
- return ext == ".csv" || ( ext == ".json" && filepath . Base ( target ) != "metadata.json" )
70
+ return slices . Contains ([] string { ".js" , ".ts" }, ext ) || slices . Contains ([] string { "metadata.json" , "data" }, target )
127
71
}
128
72
129
- //nolint:forbidigo
130
- func followLink (linkedFile string , target string ) error {
131
- source , err := os .Open (filepath .Clean (linkedFile ))
132
- if err != nil {
133
- return err
134
- }
135
- defer source .Close () //nolint:errcheck
136
-
137
- // we need to get the lined file info to create the target file with the same permissions
138
- info , err := source .Stat ()
139
- if err != nil {
140
- return err
141
- }
142
-
143
- file , err := os .OpenFile (target , os .O_CREATE | os .O_WRONLY , info .Mode ()) //nolint:gosec
144
- if err != nil {
145
- return err
73
+ // analizeMetadata extracts the dependencies from the metadata.json file
74
+ func analizeMetadata (content []byte ) (analyzer , error ) {
75
+ metadata := archiveMetadata {}
76
+ if err := json .Unmarshal (content , & metadata ); err != nil {
77
+ return nil , err
146
78
}
147
79
148
- _ , err = io .Copy (file , source )
149
- if err != nil {
150
- return err
80
+ if value , found := metadata .Env [EnvDependencies ]; found {
81
+ src := Source {
82
+ Name : EnvDependencies ,
83
+ Contents : []byte (value ),
84
+ }
85
+ return envAnalyzer (src ), nil
151
86
}
152
87
153
- err = file .Close ()
154
- if err != nil {
155
- return err
156
- }
157
- return nil
88
+ return empty , nil
158
89
}
0 commit comments