/
find.go
210 lines (179 loc) · 4.91 KB
/
find.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
package cmd
import (
"context"
"errors"
"fmt"
"github.com/fatih/color"
if_expression "github.com/golang-infrastructure/go-if-expression"
"github.com/java-sec/jar-finder/pkg/jar_util"
"github.com/java-sec/jar-finder/pkg/models"
"github.com/java-sec/jar-finder/pkg/pom_util"
"github.com/olekukonko/tablewriter"
"github.com/scagogogo/sonatype-central-sdk/pkg/api"
"github.com/spf13/cobra"
"io/fs"
"os"
"path/filepath"
"strings"
)
var (
// 要查询的jar所在的目录
dir string
// 要查询的jar文件的路径
jar string
// 查询结果输出为pom.xml文件的路径
pom string
)
func init() {
// 指定要扫描的目录
custom.PersistentFlags().StringVarP(&dir, "dir", "d", "", "Specify the directory where the jar packages you want to look in the maven central repository are located")
custom.PersistentFlags().StringVarP(&jar, "jar", "j", "", "Specify the path to the jar packages you want to find in Maven's central repository")
custom.PersistentFlags().StringVarP(&pom, "pom", "p", "", "Output the pom.xml to path")
rootCmd.AddCommand(custom)
}
var custom = &cobra.Command{
Use: "find",
Short: "Find jar in maven central repository",
Long: ``,
RunE: func(cmd *cobra.Command, args []string) error {
return Find(cmd.Context())
},
}
func Find(ctx context.Context) error {
// 参数检查
if dir == "" && jar == "" {
tips := "the dir and jar parameters specify at least one"
return errors.New(tips)
}
// 按目录查找,如果指定了目录的话
if dir != "" {
err := findByDirectory(ctx, dir)
if err != nil {
return err
}
}
if jar != "" {
return findByJar(ctx, jar)
}
return nil
}
// 查找指定的jar包
func findByJar(ctx context.Context, jarPath string) error {
stat, err := os.Stat(jarPath)
if err != nil {
if os.IsNotExist(err) {
color.Red("File %s not exists!", jarPath)
}
return err
}
jarSha1, err := jar_util.JarSha1(jarPath)
if err != nil {
color.Red("File %s sha1 error", jarPath)
return err
}
bySha1, err := api.SearchBySha1(ctx, jarSha1, 1000)
if err != nil {
color.Red("File %s query error", jarPath)
return err
}
files := make([]*models.File, 0)
for _, x := range bySha1 {
file := &models.File{
Path: jarPath,
Info: stat,
Version: x,
}
files = append(files, file)
}
renderTable(files)
if len(files) > 0 && pom != "" {
return OutputPomXMl(pom, files)
}
return nil
}
// 查找指定目录下的jar包
func findByDirectory(ctx context.Context, dir string) error {
files := make([]*models.File, 0)
err := filepath.Walk(dir, func(path string, info fs.FileInfo, err error) error {
if err != nil {
//color.Red("File %s read info error: %s", info.Name(), err.Error())
return err
} else if info.IsDir() {
// 忽略目录
return nil
}
if !strings.HasSuffix(strings.ToLower(info.Name()), ".jar") {
color.Red("File %s not jar, ignored it.", info.Name())
return nil
}
// 计算jar包的sha1
jarSha1, err := jar_util.JarSha1(path)
if err != nil {
return err
}
fmt.Println(fmt.Sprintf("File %s sha1 %s, begin search in maven central...", info.Name(), jarSha1))
versions, err := api.SearchBySha1(ctx, jarSha1, 1)
if err != nil {
return err
}
file := &models.File{
Path: path,
Info: info,
}
if len(versions) > 0 {
file.Version = versions[0]
v := file.Version
color.Green("File %s find version in maven central, groupId %s, artifactId %s, version %s", info.Name(), v.GroupId, v.ArtifactId, v.Version)
} else {
color.Red("File %s not found in maven central", info.Name())
}
files = append(files, file)
return nil
})
if err != nil {
return err
}
if len(files) != 0 {
renderTable(files)
if pom != "" {
fmt.Println(fmt.Sprintf("Result save to %s", pom))
return OutputPomXMl(pom, files)
}
}
return nil
}
// 表格渲染结果
func renderTable(files []*models.File) {
table := tablewriter.NewWriter(os.Stdout)
table.SetBorder(true)
table.SetHeader([]string{"File", "In Maven Repo", "Group ID", "Artifact ID", "Version"})
table.SetAlignment(tablewriter.ALIGN_CENTER)
for _, f := range files {
row := []string{
f.Info.Name(),
if_expression.Return(f.ExistsMaven(), color.GreenString("Y"), color.RedString("N")),
}
if f.Version != nil {
row = append(row, f.Version.GroupId)
row = append(row, f.Version.ArtifactId)
row = append(row, f.Version.Version)
} else {
row = append(row, "", "", "")
}
table.Append(row)
}
table.Render()
}
// OutputPomXMl 把查询结果输出为pom.xml文件
func OutputPomXMl(pomPath string, files []*models.File) error {
// 目录不存在时自动创建
_ = os.MkdirAll(filepath.Dir(pomPath), os.ModePerm)
// 然后开始构建pom.xml文件并写入到指定位置,如果文件已经存在的话则会覆盖掉
pomXMl := pom_util.BuildPomXml(files)
file, err := os.OpenFile(pom, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm)
if err != nil {
return err
}
_, err = file.Write([]byte(pomXMl))
return err
}