forked from golang/dep
-
Notifications
You must be signed in to change notification settings - Fork 0
/
trace.go
205 lines (172 loc) · 5.35 KB
/
trace.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
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package gps
import (
"fmt"
"strconv"
"strings"
"github.com/golang/dep/gps/pkgtree"
)
const (
successChar = "✓"
successCharSp = successChar + " "
failChar = "✗"
failCharSp = failChar + " "
backChar = "←"
innerIndent = " "
)
func (s *solver) traceCheckPkgs(bmi bimodalIdentifier) {
if s.tl == nil {
return
}
prefix := getprei(len(s.vqs) + 1)
s.tl.Printf("%s\n", tracePrefix(fmt.Sprintf("? revisit %s to add %v pkgs", bmi.id, len(bmi.pl)), prefix, prefix))
}
func (s *solver) traceCheckQueue(q *versionQueue, bmi bimodalIdentifier, cont bool, offset int) {
if s.tl == nil {
return
}
prefix := getprei(len(s.vqs) + offset)
vlen := strconv.Itoa(len(q.pi))
if !q.allLoaded {
vlen = "at least " + vlen
}
// TODO(sdboyer) how...to list the packages in the limited space we have?
var verb string
indent := ""
if cont {
// Continue is an "inner" message.. indenting
verb = "continue"
vlen += " more"
indent = innerIndent
} else {
verb = "attempt"
}
s.tl.Printf("%s\n", tracePrefix(fmt.Sprintf("%s? %s %s with %v pkgs; %s versions to try", indent, verb, bmi.id, len(bmi.pl), vlen), prefix, prefix))
}
// traceStartBacktrack is called with the bmi that first failed, thus initiating
// backtracking
func (s *solver) traceStartBacktrack(bmi bimodalIdentifier, err error, pkgonly bool) {
if s.tl == nil {
return
}
var msg string
if pkgonly {
msg = fmt.Sprintf("%s%s could not add %v pkgs to %s; begin backtrack", innerIndent, backChar, len(bmi.pl), bmi.id)
} else {
msg = fmt.Sprintf("%s%s no more versions of %s to try; begin backtrack", innerIndent, backChar, bmi.id)
}
prefix := getprei(len(s.sel.projects))
s.tl.Printf("%s\n", tracePrefix(msg, prefix, prefix))
}
// traceBacktrack is called when a package or project is poppped off during
// backtracking
func (s *solver) traceBacktrack(bmi bimodalIdentifier, pkgonly bool) {
if s.tl == nil {
return
}
var msg string
if pkgonly {
msg = fmt.Sprintf("%s backtrack: popped %v pkgs from %s", backChar, len(bmi.pl), bmi.id)
} else {
msg = fmt.Sprintf("%s backtrack: no more versions of %s to try", backChar, bmi.id)
}
prefix := getprei(len(s.sel.projects))
s.tl.Printf("%s\n", tracePrefix(msg, prefix, prefix))
}
// Called just once after solving has finished, whether success or not
func (s *solver) traceFinish(sol solution, err error) {
if s.tl == nil {
return
}
if err == nil {
var pkgcount int
for _, lp := range sol.Projects() {
pkgcount += len(lp.Packages())
}
s.tl.Printf("%s%s found solution with %v packages from %v projects", innerIndent, successChar, pkgcount, len(sol.Projects()))
} else {
s.tl.Printf("%s%s solving failed", innerIndent, failChar)
}
}
// traceSelectRoot is called just once, when the root project is selected
func (s *solver) traceSelectRoot(ptree pkgtree.PackageTree, cdeps []completeDep) {
if s.tl == nil {
return
}
// This duplicates work a bit, but we're in trace mode and it's only once,
// so who cares
rm, _ := ptree.ToReachMap(true, true, false, s.rd.ir)
s.tl.Printf("Root project is %q", s.rd.rpt.ImportRoot)
var expkgs int
for _, cdep := range cdeps {
expkgs += len(cdep.pl)
}
// TODO(sdboyer) include info on ignored pkgs/imports, etc.
s.tl.Printf(" %v transitively valid internal packages", len(rm))
s.tl.Printf(" %v external packages imported from %v projects", expkgs, len(cdeps))
s.tl.Printf("(0) " + successCharSp + "select (root)")
}
// traceSelect is called when an atom is successfully selected
func (s *solver) traceSelect(awp atomWithPackages, pkgonly bool) {
if s.tl == nil {
return
}
var msg string
if pkgonly {
msg = fmt.Sprintf("%s%s include %v more pkgs from %s", innerIndent, successChar, len(awp.pl), a2vs(awp.a))
} else {
msg = fmt.Sprintf("%s select %s w/%v pkgs", successChar, a2vs(awp.a), len(awp.pl))
}
prefix := getprei(len(s.sel.projects) - 1)
s.tl.Printf("%s\n", tracePrefix(msg, prefix, prefix))
}
func (s *solver) traceInfo(args ...interface{}) {
if s.tl == nil {
return
}
if len(args) == 0 {
panic("must pass at least one param to traceInfo")
}
preflen := len(s.sel.projects)
var msg string
switch data := args[0].(type) {
case string:
msg = tracePrefix(innerIndent+fmt.Sprintf(data, args[1:]...), " ", " ")
case traceError:
preflen++
// We got a special traceError, use its custom method
msg = tracePrefix(innerIndent+data.traceString(), " ", failCharSp)
case error:
// Regular error; still use the x leader but default Error() string
msg = tracePrefix(innerIndent+data.Error(), " ", failCharSp)
default:
// panic here because this can *only* mean a stupid internal bug
panic(fmt.Sprintf("canary - unknown type passed as first param to traceInfo %T", data))
}
prefix := getprei(preflen)
s.tl.Printf("%s\n", tracePrefix(msg, prefix, prefix))
}
func getprei(i int) string {
var s string
if i < 10 {
s = fmt.Sprintf("(%d) ", i)
} else if i < 100 {
s = fmt.Sprintf("(%d) ", i)
} else {
s = fmt.Sprintf("(%d) ", i)
}
return s
}
func tracePrefix(msg, sep, fsep string) string {
parts := strings.Split(strings.TrimSuffix(msg, "\n"), "\n")
for k, str := range parts {
if k == 0 {
parts[k] = fsep + str
} else {
parts[k] = sep + str
}
}
return strings.Join(parts, "\n")
}