github.com/golang/dep@v0.5.4/gps/trace.go (about) 1 // Copyright 2017 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package gps 6 7 import ( 8 "fmt" 9 "strconv" 10 "strings" 11 12 "github.com/golang/dep/gps/pkgtree" 13 ) 14 15 const ( 16 successChar = "✓" 17 successCharSp = successChar + " " 18 failChar = "✗" 19 failCharSp = failChar + " " 20 backChar = "←" 21 innerIndent = " " 22 ) 23 24 func (s *solver) traceCheckPkgs(bmi bimodalIdentifier) { 25 if s.tl == nil { 26 return 27 } 28 29 prefix := getprei(len(s.vqs) + 1) 30 s.tl.Printf("%s\n", tracePrefix(fmt.Sprintf("? revisit %s to add %v pkgs", bmi.id, len(bmi.pl)), prefix, prefix)) 31 } 32 33 func (s *solver) traceCheckQueue(q *versionQueue, bmi bimodalIdentifier, cont bool, offset int) { 34 if s.tl == nil { 35 return 36 } 37 38 prefix := getprei(len(s.vqs) + offset) 39 vlen := strconv.Itoa(len(q.pi)) 40 if !q.allLoaded { 41 vlen = "at least " + vlen 42 } 43 44 // TODO(sdboyer) how...to list the packages in the limited space we have? 45 var verb string 46 indent := "" 47 if cont { 48 // Continue is an "inner" message.. indenting 49 verb = "continue" 50 vlen += " more" 51 indent = innerIndent 52 } else { 53 verb = "attempt" 54 } 55 56 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)) 57 } 58 59 // traceStartBacktrack is called with the bmi that first failed, thus initiating 60 // backtracking 61 func (s *solver) traceStartBacktrack(bmi bimodalIdentifier, err error, pkgonly bool) { 62 if s.tl == nil { 63 return 64 } 65 66 var msg string 67 if pkgonly { 68 msg = fmt.Sprintf("%s%s could not add %v pkgs to %s; begin backtrack", innerIndent, backChar, len(bmi.pl), bmi.id) 69 } else { 70 msg = fmt.Sprintf("%s%s no more versions of %s to try; begin backtrack", innerIndent, backChar, bmi.id) 71 } 72 73 prefix := getprei(len(s.sel.projects)) 74 s.tl.Printf("%s\n", tracePrefix(msg, prefix, prefix)) 75 } 76 77 // traceBacktrack is called when a package or project is poppped off during 78 // backtracking 79 func (s *solver) traceBacktrack(bmi bimodalIdentifier, pkgonly bool) { 80 if s.tl == nil { 81 return 82 } 83 84 var msg string 85 if pkgonly { 86 msg = fmt.Sprintf("%s backtrack: popped %v pkgs from %s", backChar, len(bmi.pl), bmi.id) 87 } else { 88 msg = fmt.Sprintf("%s backtrack: no more versions of %s to try", backChar, bmi.id) 89 } 90 91 prefix := getprei(len(s.sel.projects)) 92 s.tl.Printf("%s\n", tracePrefix(msg, prefix, prefix)) 93 } 94 95 // Called just once after solving has finished, whether success or not 96 func (s *solver) traceFinish(sol solution, err error) { 97 if s.tl == nil { 98 return 99 } 100 101 if err == nil { 102 var pkgcount int 103 for _, lp := range sol.Projects() { 104 pkgcount += len(lp.Packages()) 105 } 106 s.tl.Printf("%s%s found solution with %v packages from %v projects", innerIndent, successChar, pkgcount, len(sol.Projects())) 107 } else { 108 s.tl.Printf("%s%s solving failed", innerIndent, failChar) 109 } 110 } 111 112 // traceSelectRoot is called just once, when the root project is selected 113 func (s *solver) traceSelectRoot(ptree pkgtree.PackageTree, cdeps []completeDep) { 114 if s.tl == nil { 115 return 116 } 117 118 // This duplicates work a bit, but we're in trace mode and it's only once, 119 // so who cares 120 rm, _ := ptree.ToReachMap(true, true, false, s.rd.ir) 121 122 s.tl.Printf("Root project is %q", s.rd.rpt.ImportRoot) 123 124 var expkgs int 125 for _, cdep := range cdeps { 126 expkgs += len(cdep.pl) 127 } 128 129 // TODO(sdboyer) include info on ignored pkgs/imports, etc. 130 s.tl.Printf(" %v transitively valid internal packages", len(rm)) 131 s.tl.Printf(" %v external packages imported from %v projects", expkgs, len(cdeps)) 132 s.tl.Printf("(0) " + successCharSp + "select (root)") 133 } 134 135 // traceSelect is called when an atom is successfully selected 136 func (s *solver) traceSelect(awp atomWithPackages, pkgonly bool) { 137 if s.tl == nil { 138 return 139 } 140 141 var msg string 142 if pkgonly { 143 msg = fmt.Sprintf("%s%s include %v more pkgs from %s", innerIndent, successChar, len(awp.pl), a2vs(awp.a)) 144 } else { 145 msg = fmt.Sprintf("%s select %s w/%v pkgs", successChar, a2vs(awp.a), len(awp.pl)) 146 } 147 148 prefix := getprei(len(s.sel.projects) - 1) 149 s.tl.Printf("%s\n", tracePrefix(msg, prefix, prefix)) 150 } 151 152 func (s *solver) traceInfo(args ...interface{}) { 153 if s.tl == nil { 154 return 155 } 156 157 if len(args) == 0 { 158 panic("must pass at least one param to traceInfo") 159 } 160 161 preflen := len(s.sel.projects) 162 var msg string 163 switch data := args[0].(type) { 164 case string: 165 msg = tracePrefix(innerIndent+fmt.Sprintf(data, args[1:]...), " ", " ") 166 case traceError: 167 preflen++ 168 // We got a special traceError, use its custom method 169 msg = tracePrefix(innerIndent+data.traceString(), " ", failCharSp) 170 case error: 171 // Regular error; still use the x leader but default Error() string 172 msg = tracePrefix(innerIndent+data.Error(), " ", failCharSp) 173 default: 174 // panic here because this can *only* mean a stupid internal bug 175 panic(fmt.Sprintf("canary - unknown type passed as first param to traceInfo %T", data)) 176 } 177 178 prefix := getprei(preflen) 179 s.tl.Printf("%s\n", tracePrefix(msg, prefix, prefix)) 180 } 181 182 func getprei(i int) string { 183 var s string 184 if i < 10 { 185 s = fmt.Sprintf("(%d) ", i) 186 } else if i < 100 { 187 s = fmt.Sprintf("(%d) ", i) 188 } else { 189 s = fmt.Sprintf("(%d) ", i) 190 } 191 return s 192 } 193 194 func tracePrefix(msg, sep, fsep string) string { 195 parts := strings.Split(strings.TrimSuffix(msg, "\n"), "\n") 196 for k, str := range parts { 197 if k == 0 { 198 parts[k] = fsep + str 199 } else { 200 parts[k] = sep + str 201 } 202 } 203 204 return strings.Join(parts, "\n") 205 }