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  }