Source file src/cmd/covdata/merge.go

     1  // Copyright 2022 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 main
     6  
     7  // This file contains functions and apis to support the "merge"
     8  // subcommand of "go tool covdata".
     9  
    10  import (
    11  	"flag"
    12  	"fmt"
    13  	"internal/coverage"
    14  	"internal/coverage/cmerge"
    15  	"internal/coverage/decodecounter"
    16  	"internal/coverage/decodemeta"
    17  	"internal/coverage/pods"
    18  	"os"
    19  )
    20  
    21  var outdirflag *string
    22  var pcombineflag *bool
    23  
    24  func makeMergeOp() covOperation {
    25  	outdirflag = flag.String("o", "", "Output directory to write")
    26  	pcombineflag = flag.Bool("pcombine", false, "Combine profiles derived from distinct program executables")
    27  	m := &mstate{
    28  		mm: newMetaMerge(),
    29  	}
    30  	return m
    31  }
    32  
    33  // mstate encapsulates state and provides methods for implementing the
    34  // merge operation. This type implements the CovDataVisitor interface,
    35  // and is designed to be used in concert with the CovDataReader
    36  // utility, which abstracts away most of the grubby details of reading
    37  // coverage data files. Most of the heavy lifting for merging is done
    38  // using apis from 'metaMerge' (this is mainly a wrapper around that
    39  // functionality).
    40  type mstate struct {
    41  	mm *metaMerge
    42  }
    43  
    44  func (m *mstate) Usage(msg string) {
    45  	if len(msg) > 0 {
    46  		fmt.Fprintf(os.Stderr, "error: %s\n", msg)
    47  	}
    48  	fmt.Fprintf(os.Stderr, "usage: go tool covdata merge -i=<directories> -o=<dir>\n\n")
    49  	flag.PrintDefaults()
    50  	fmt.Fprintf(os.Stderr, "\nExamples:\n\n")
    51  	fmt.Fprintf(os.Stderr, "  go tool covdata merge -i=dir1,dir2,dir3 -o=outdir\n\n")
    52  	fmt.Fprintf(os.Stderr, "  \tmerges all files in dir1/dir2/dir3\n")
    53  	fmt.Fprintf(os.Stderr, "  \tinto output dir outdir\n")
    54  	Exit(2)
    55  }
    56  
    57  func (m *mstate) Setup() {
    58  	if *indirsflag == "" {
    59  		m.Usage("select input directories with '-i' option")
    60  	}
    61  	if *outdirflag == "" {
    62  		m.Usage("select output directory with '-o' option")
    63  	}
    64  	m.mm.SetModeMergePolicy(cmerge.ModeMergeRelaxed)
    65  }
    66  
    67  func (m *mstate) BeginPod(p pods.Pod) {
    68  	m.mm.beginPod()
    69  }
    70  
    71  func (m *mstate) EndPod(p pods.Pod) {
    72  	m.mm.endPod(*pcombineflag)
    73  }
    74  
    75  func (m *mstate) BeginCounterDataFile(cdf string, cdr *decodecounter.CounterDataReader, dirIdx int) {
    76  	dbgtrace(2, "visit counter data file %s dirIdx %d", cdf, dirIdx)
    77  	m.mm.beginCounterDataFile(cdr)
    78  }
    79  
    80  func (m *mstate) EndCounterDataFile(cdf string, cdr *decodecounter.CounterDataReader, dirIdx int) {
    81  }
    82  
    83  func (m *mstate) VisitFuncCounterData(data decodecounter.FuncPayload) {
    84  	m.mm.visitFuncCounterData(data)
    85  }
    86  
    87  func (m *mstate) EndCounters() {
    88  }
    89  
    90  func (m *mstate) VisitMetaDataFile(mdf string, mfr *decodemeta.CoverageMetaFileReader) {
    91  	m.mm.visitMetaDataFile(mdf, mfr)
    92  }
    93  
    94  func (m *mstate) BeginPackage(pd *decodemeta.CoverageMetaDataDecoder, pkgIdx uint32) {
    95  	dbgtrace(3, "VisitPackage(pk=%d path=%s)", pkgIdx, pd.PackagePath())
    96  	m.mm.visitPackage(pd, pkgIdx, *pcombineflag)
    97  }
    98  
    99  func (m *mstate) EndPackage(pd *decodemeta.CoverageMetaDataDecoder, pkgIdx uint32) {
   100  }
   101  
   102  func (m *mstate) VisitFunc(pkgIdx uint32, fnIdx uint32, fd *coverage.FuncDesc) {
   103  	m.mm.visitFunc(pkgIdx, fnIdx, fd, mergeMode, *pcombineflag)
   104  }
   105  
   106  func (m *mstate) Finish() {
   107  	if *pcombineflag {
   108  		finalHash := m.mm.emitMeta(*outdirflag, true)
   109  		m.mm.emitCounters(*outdirflag, finalHash)
   110  	}
   111  }
   112  

View as plain text