@@ -7,11 +7,16 @@ import (
7
7
"os"
8
8
"os/exec"
9
9
"path/filepath"
10
+ "regexp"
11
+ "strconv"
10
12
"strings"
11
13
12
14
"golang.org/x/tools/go/vcs"
13
15
)
14
16
17
+ // majorVersionRegexp checks if an import path contains a major version suffix.
18
+ var majorVersionRegexp = regexp .MustCompile (`([/.])v([0-9]+)$` )
19
+
15
20
func clone (srcdir , repo string ) error {
16
21
done := make (chan struct {})
17
22
defer close (done )
@@ -64,6 +69,24 @@ func removeVendor(gopath string) (found bool, _ error) {
64
69
return found , err
65
70
}
66
71
72
+ // otherVersions guesses the import paths of potential other major version
73
+ // of the given module import path, based on [majorVersionRegex].
74
+ func otherVersions (mod string ) (mods []string ) {
75
+ matches := majorVersionRegexp .FindStringSubmatch (mod )
76
+ if matches == nil {
77
+ return
78
+ }
79
+ matchFull , matchSep , matchVer := matches [0 ], matches [1 ], matches [2 ]
80
+ matchIndex := len (mod ) - len (matchFull )
81
+ prefix := mod [:matchIndex ]
82
+ version , _ := strconv .Atoi (matchVer )
83
+ for v := version - 1 ; v > 1 ; v -- {
84
+ mods = append (mods , prefix + matchSep + "v" + strconv .Itoa (v ))
85
+ }
86
+ mods = append (mods , prefix )
87
+ return
88
+ }
89
+
67
90
func estimate (importpath string ) error {
68
91
removeTemp := func (path string ) {
69
92
if err := forceRemoveAll (path ); err != nil {
@@ -167,7 +190,6 @@ func estimate(importpath string) error {
167
190
// Analyse the dependency graph
168
191
var lines []string
169
192
seen := make (map [string ]bool )
170
- rrseen := make (map [string ]bool )
171
193
var visit func (n * Node , indent int )
172
194
visit = func (n * Node , indent int ) {
173
195
// Get the module name without its version, as go mod graph
@@ -183,19 +205,36 @@ func estimate(importpath string) error {
183
205
if mod == "go" || mod == "toolchain" {
184
206
return
185
207
}
186
- rr , err := vcs .RepoRootForImportPath (mod , false )
187
- if err != nil {
188
- log .Printf ("Could not determine repo path for import path %q: %v\n " , mod , err )
189
- return
208
+ if _ , ok := golangBinaries [mod ]; ok {
209
+ return // already packaged in Debian
190
210
}
191
- if rrseen [rr .Root ] {
192
- return
211
+ var debianVersion string
212
+ // Check for potential other major versions already in Debian.
213
+ for _ , otherVersion := range otherVersions (mod ) {
214
+ if _ , ok := golangBinaries [otherVersion ]; ok {
215
+ debianVersion = otherVersion
216
+ break
217
+ }
193
218
}
194
- rrseen [rr .Root ] = true
195
- if _ , ok := golangBinaries [rr .Root ]; ok {
196
- return // already packaged in Debian
219
+ if debianVersion == "" {
220
+ // When multiple modules are developped in the same repo,
221
+ // the repo root is often used as the import path metadata
222
+ // in Debian, so we do a last try with that.
223
+ rr , err := vcs .RepoRootForImportPath (mod , false )
224
+ if err != nil {
225
+ log .Printf ("Could not determine repo path for import path %q: %v\n " , mod , err )
226
+ } else if _ , ok := golangBinaries [rr .Root ]; ok {
227
+ // Log info to indicate that it is an approximate match
228
+ // but consider that it is packaged and skip the children.
229
+ log .Printf ("%s is packaged as %s in Debian" , mod , rr .Root )
230
+ return
231
+ }
232
+ }
233
+ if debianVersion != "" {
234
+ lines = append (lines , fmt .Sprintf ("%s%s\t (%s in Debian)" , strings .Repeat (" " , indent ), mod , debianVersion ))
235
+ } else {
236
+ lines = append (lines , fmt .Sprintf ("%s%s" , strings .Repeat (" " , indent ), mod ))
197
237
}
198
- lines = append (lines , fmt .Sprintf ("%s%s" , strings .Repeat (" " , indent ), rr .Root ))
199
238
for _ , n := range n .children {
200
239
visit (n , indent + 1 )
201
240
}
0 commit comments