You've already forked postgres_exporter
mirror of
https://github.com/prometheus-community/postgres_exporter.git
synced 2025-08-08 04:42:07 +03:00
Add cross-compilation Makefile targets and tar-based releases.
Revamp the build system to be more inline with other Prometheus exporters. Notably add Darwin and Windows build targets, and add support for releases using tar files.
This commit is contained in:
134
tools/vendor/github.com/mibk/dupl/main.go
generated
vendored
134
tools/vendor/github.com/mibk/dupl/main.go
generated
vendored
@@ -12,7 +12,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/mibk/dupl/job"
|
||||
"github.com/mibk/dupl/output"
|
||||
"github.com/mibk/dupl/printer"
|
||||
"github.com/mibk/dupl/syntax"
|
||||
)
|
||||
|
||||
@@ -20,18 +20,18 @@ const defaultThreshold = 15
|
||||
|
||||
var (
|
||||
paths = []string{"."}
|
||||
vendor = flag.Bool("vendor", false, "check files in vendor directory")
|
||||
verbose = flag.Bool("verbose", false, "explain what is being done")
|
||||
threshold = flag.Int("threshold", defaultThreshold, "minimum token sequence as a clone")
|
||||
files = flag.Bool("files", false, "files names from stdin")
|
||||
vendor = flag.Bool("vendor", false, "")
|
||||
verbose = flag.Bool("verbose", false, "")
|
||||
threshold = flag.Int("threshold", defaultThreshold, "")
|
||||
files = flag.Bool("files", false, "")
|
||||
|
||||
html = flag.Bool("html", false, "html output")
|
||||
plumbing = flag.Bool("plumbing", false, "plumbing output for consumption by scripts or tools")
|
||||
html = flag.Bool("html", false, "")
|
||||
plumbing = flag.Bool("plumbing", false, "")
|
||||
)
|
||||
|
||||
const (
|
||||
vendorDirPrefix = "vendor" + string(filepath.Separator)
|
||||
vendorDirInPath = string(filepath.Separator) + "vendor" + string(filepath.Separator)
|
||||
vendorDirInPath = string(filepath.Separator) + vendorDirPrefix
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -39,43 +39,6 @@ func init() {
|
||||
flag.IntVar(threshold, "t", defaultThreshold, "alias for -threshold")
|
||||
}
|
||||
|
||||
func usage() {
|
||||
fmt.Fprintln(os.Stderr, `Usage of dupl:
|
||||
dupl [flags] [paths]
|
||||
|
||||
Paths:
|
||||
If the given path is a file, dupl will use it regardless of
|
||||
the file extension. If it is a directory it will recursively
|
||||
search for *.go files in that directory.
|
||||
|
||||
If no path is given dupl will recursively search for *.go
|
||||
files in the current directory.
|
||||
|
||||
Flags:
|
||||
-files
|
||||
read file names from stdin one at each line
|
||||
-html
|
||||
output the results as HTML, including duplicate code fragments
|
||||
-plumbing
|
||||
plumbing (easy-to-parse) output for consumption by scripts or tools
|
||||
-t, -threshold size
|
||||
minimum token sequence size as a clone (default 15)
|
||||
-vendor
|
||||
check files in vendor directory
|
||||
-v, -verbose
|
||||
explain what is being done
|
||||
|
||||
Examples:
|
||||
dupl -t 100
|
||||
Search clones in the current directory of size at least
|
||||
100 tokens.
|
||||
dupl $(find app/ -name '*_test.go')
|
||||
Search for clones in tests in the app directory.
|
||||
find app/ -name '*_test.go' |dupl -files
|
||||
The same as above.`)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
@@ -110,7 +73,17 @@ func main() {
|
||||
}
|
||||
close(duplChan)
|
||||
}()
|
||||
printDupls(duplChan)
|
||||
|
||||
newPrinter := printer.NewText
|
||||
if *html {
|
||||
newPrinter = printer.NewHTML
|
||||
} else if *plumbing {
|
||||
newPrinter = printer.NewPlumbing
|
||||
}
|
||||
p := newPrinter(os.Stdout, ioutil.ReadFile)
|
||||
if err := printDupls(p, duplChan); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func filesFeed() chan string {
|
||||
@@ -120,10 +93,7 @@ func filesFeed() chan string {
|
||||
s := bufio.NewScanner(os.Stdin)
|
||||
for s.Scan() {
|
||||
f := s.Text()
|
||||
if strings.HasPrefix(f, "./") {
|
||||
f = f[2:]
|
||||
}
|
||||
fchan <- f
|
||||
fchan <- strings.TrimPrefix(f, "./")
|
||||
}
|
||||
close(fchan)
|
||||
}()
|
||||
@@ -160,7 +130,7 @@ func crawlPaths(paths []string) chan string {
|
||||
return fchan
|
||||
}
|
||||
|
||||
func printDupls(duplChan <-chan syntax.Match) {
|
||||
func printDupls(p printer.Printer, duplChan <-chan syntax.Match) error {
|
||||
groups := make(map[string][][]*syntax.Node)
|
||||
for dupl := range duplChan {
|
||||
groups[dupl.Hash] = append(groups[dupl.Hash], dupl.Frags...)
|
||||
@@ -171,32 +141,18 @@ func printDupls(duplChan <-chan syntax.Match) {
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
p := getPrinter()
|
||||
if err := p.PrintHeader(); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, k := range keys {
|
||||
uniq := unique(groups[k])
|
||||
if len(uniq) > 1 {
|
||||
if err := p.Print(uniq); err != nil {
|
||||
log.Fatal(err)
|
||||
if err := p.PrintClones(uniq); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
p.Finish()
|
||||
}
|
||||
|
||||
func getPrinter() output.Printer {
|
||||
var fr fileReader
|
||||
if *html {
|
||||
return output.NewHTMLPrinter(os.Stdout, fr)
|
||||
} else if *plumbing {
|
||||
return output.NewPlumbingPrinter(os.Stdout, fr)
|
||||
}
|
||||
return output.NewTextPrinter(os.Stdout, fr)
|
||||
}
|
||||
|
||||
type fileReader struct{}
|
||||
|
||||
func (fileReader) ReadFile(filename string) ([]byte, error) {
|
||||
return ioutil.ReadFile(filename)
|
||||
return p.PrintFooter()
|
||||
}
|
||||
|
||||
func unique(group [][]*syntax.Node) [][]*syntax.Node {
|
||||
@@ -217,3 +173,39 @@ func unique(group [][]*syntax.Node) [][]*syntax.Node {
|
||||
}
|
||||
return newGroup
|
||||
}
|
||||
|
||||
func usage() {
|
||||
fmt.Fprintln(os.Stderr, `Usage: dupl [flags] [paths]
|
||||
|
||||
Paths:
|
||||
If the given path is a file, dupl will use it regardless of
|
||||
the file extension. If it is a directory, it will recursively
|
||||
search for *.go files in that directory.
|
||||
|
||||
If no path is given, dupl will recursively search for *.go
|
||||
files in the current directory.
|
||||
|
||||
Flags:
|
||||
-files
|
||||
read file names from stdin one at each line
|
||||
-html
|
||||
output the results as HTML, including duplicate code fragments
|
||||
-plumbing
|
||||
plumbing (easy-to-parse) output for consumption by scripts or tools
|
||||
-t, -threshold size
|
||||
minimum token sequence size as a clone (default 15)
|
||||
-vendor
|
||||
check files in vendor directory
|
||||
-v, -verbose
|
||||
explain what is being done
|
||||
|
||||
Examples:
|
||||
dupl -t 100
|
||||
Search clones in the current directory of size at least
|
||||
100 tokens.
|
||||
dupl $(find app/ -name '*_test.go')
|
||||
Search for clones in tests in the app directory.
|
||||
find app/ -name '*_test.go' |dupl -files
|
||||
The same as above.`)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
120
tools/vendor/github.com/mibk/dupl/printer/html.go
generated
vendored
Normal file
120
tools/vendor/github.com/mibk/dupl/printer/html.go
generated
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
package printer
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"regexp"
|
||||
"sort"
|
||||
|
||||
"github.com/mibk/dupl/syntax"
|
||||
)
|
||||
|
||||
type html struct {
|
||||
iota int
|
||||
w io.Writer
|
||||
ReadFile
|
||||
}
|
||||
|
||||
func NewHTML(w io.Writer, fread ReadFile) Printer {
|
||||
return &html{w: w, ReadFile: fread}
|
||||
}
|
||||
|
||||
func (p *html) PrintHeader() error {
|
||||
_, err := fmt.Fprint(p.w, `<!DOCTYPE html>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Duplicates</title>
|
||||
<style>
|
||||
pre {
|
||||
background-color: #FFD;
|
||||
border: 1px solid #E2E2E2;
|
||||
padding: 1ex;
|
||||
}
|
||||
</style>
|
||||
`)
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *html) PrintClones(dups [][]*syntax.Node) error {
|
||||
p.iota++
|
||||
fmt.Fprintf(p.w, "<h1>#%d found %d clones</h1>\n", p.iota, len(dups))
|
||||
|
||||
clones := make([]clone, len(dups))
|
||||
for i, dup := range dups {
|
||||
cnt := len(dup)
|
||||
if cnt == 0 {
|
||||
panic("zero length dup")
|
||||
}
|
||||
nstart := dup[0]
|
||||
nend := dup[cnt-1]
|
||||
|
||||
file, err := p.ReadFile(nstart.Filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
lineStart, _ := blockLines(file, nstart.Pos, nend.End)
|
||||
cl := clone{filename: nstart.Filename, lineStart: lineStart}
|
||||
start := findLineBeg(file, nstart.Pos)
|
||||
content := append(toWhitespace(file[start:nstart.Pos]), file[nstart.Pos:nend.End]...)
|
||||
cl.fragment = deindent(content)
|
||||
clones[i] = cl
|
||||
}
|
||||
|
||||
sort.Sort(byNameAndLine(clones))
|
||||
for _, cl := range clones {
|
||||
fmt.Fprintf(p.w, "<h2>%s:%d</h2>\n<pre>%s</pre>\n", cl.filename, cl.lineStart, cl.fragment)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*html) PrintFooter() error { return nil }
|
||||
|
||||
func findLineBeg(file []byte, index int) int {
|
||||
for i := index; i >= 0; i-- {
|
||||
if file[i] == '\n' {
|
||||
return i + 1
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func toWhitespace(str []byte) []byte {
|
||||
var out []byte
|
||||
for _, c := range bytes.Runes(str) {
|
||||
if c == '\t' {
|
||||
out = append(out, '\t')
|
||||
} else {
|
||||
out = append(out, ' ')
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func deindent(block []byte) []byte {
|
||||
const maxVal = 99
|
||||
min := maxVal
|
||||
re := regexp.MustCompile(`(^|\n)(\t*)\S`)
|
||||
for _, line := range re.FindAllSubmatch(block, -1) {
|
||||
indent := line[2]
|
||||
if len(indent) < min {
|
||||
min = len(indent)
|
||||
}
|
||||
}
|
||||
if min == 0 || min == maxVal {
|
||||
return block
|
||||
}
|
||||
block = block[min:]
|
||||
Loop:
|
||||
for i := 0; i < len(block); i++ {
|
||||
if block[i] == '\n' && i != len(block)-1 {
|
||||
for j := 0; j < min; j++ {
|
||||
if block[i+j+1] != '\t' {
|
||||
continue Loop
|
||||
}
|
||||
}
|
||||
block = append(block[:i+1], block[i+1+min:]...)
|
||||
}
|
||||
}
|
||||
return block
|
||||
}
|
36
tools/vendor/github.com/mibk/dupl/printer/plumbing.go
generated
vendored
Normal file
36
tools/vendor/github.com/mibk/dupl/printer/plumbing.go
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
package printer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"sort"
|
||||
|
||||
"github.com/mibk/dupl/syntax"
|
||||
)
|
||||
|
||||
type plumbing struct {
|
||||
w io.Writer
|
||||
ReadFile
|
||||
}
|
||||
|
||||
func NewPlumbing(w io.Writer, fread ReadFile) Printer {
|
||||
return &plumbing{w, fread}
|
||||
}
|
||||
|
||||
func (p *plumbing) PrintHeader() error { return nil }
|
||||
|
||||
func (p *plumbing) PrintClones(dups [][]*syntax.Node) error {
|
||||
clones, err := prepareClonesInfo(p.ReadFile, dups)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sort.Sort(byNameAndLine(clones))
|
||||
for i, cl := range clones {
|
||||
nextCl := clones[(i+1)%len(clones)]
|
||||
fmt.Fprintf(p.w, "%s:%d-%d: duplicate of %s:%d-%d\n", cl.filename, cl.lineStart, cl.lineEnd,
|
||||
nextCl.filename, nextCl.lineStart, nextCl.lineEnd)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *plumbing) PrintFooter() error { return nil }
|
11
tools/vendor/github.com/mibk/dupl/printer/printer.go
generated
vendored
Normal file
11
tools/vendor/github.com/mibk/dupl/printer/printer.go
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
package printer
|
||||
|
||||
import "github.com/mibk/dupl/syntax"
|
||||
|
||||
type ReadFile func(filename string) ([]byte, error)
|
||||
|
||||
type Printer interface {
|
||||
PrintHeader() error
|
||||
PrintClones(dups [][]*syntax.Node) error
|
||||
PrintFooter() error
|
||||
}
|
100
tools/vendor/github.com/mibk/dupl/printer/text.go
generated
vendored
Normal file
100
tools/vendor/github.com/mibk/dupl/printer/text.go
generated
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
package printer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"sort"
|
||||
|
||||
"github.com/mibk/dupl/syntax"
|
||||
)
|
||||
|
||||
type text struct {
|
||||
cnt int
|
||||
w io.Writer
|
||||
ReadFile
|
||||
}
|
||||
|
||||
func NewText(w io.Writer, fread ReadFile) Printer {
|
||||
return &text{w: w, ReadFile: fread}
|
||||
}
|
||||
|
||||
func (p *text) PrintHeader() error { return nil }
|
||||
|
||||
func (p *text) PrintClones(dups [][]*syntax.Node) error {
|
||||
p.cnt++
|
||||
fmt.Fprintf(p.w, "found %d clones:\n", len(dups))
|
||||
clones, err := prepareClonesInfo(p.ReadFile, dups)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sort.Sort(byNameAndLine(clones))
|
||||
for _, cl := range clones {
|
||||
fmt.Fprintf(p.w, " %s:%d,%d\n", cl.filename, cl.lineStart, cl.lineEnd)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *text) PrintFooter() error {
|
||||
_, err := fmt.Fprintf(p.w, "\nFound total %d clone groups.\n", p.cnt)
|
||||
return err
|
||||
}
|
||||
|
||||
func prepareClonesInfo(fread ReadFile, dups [][]*syntax.Node) ([]clone, error) {
|
||||
clones := make([]clone, len(dups))
|
||||
for i, dup := range dups {
|
||||
cnt := len(dup)
|
||||
if cnt == 0 {
|
||||
panic("zero length dup")
|
||||
}
|
||||
nstart := dup[0]
|
||||
nend := dup[cnt-1]
|
||||
|
||||
file, err := fread(nstart.Filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cl := clone{filename: nstart.Filename}
|
||||
cl.lineStart, cl.lineEnd = blockLines(file, nstart.Pos, nend.End)
|
||||
clones[i] = cl
|
||||
}
|
||||
return clones, nil
|
||||
}
|
||||
|
||||
func blockLines(file []byte, from, to int) (int, int) {
|
||||
line := 1
|
||||
lineStart, lineEnd := 0, 0
|
||||
for offset, b := range file {
|
||||
if b == '\n' {
|
||||
line++
|
||||
}
|
||||
if offset == from {
|
||||
lineStart = line
|
||||
}
|
||||
if offset == to-1 {
|
||||
lineEnd = line
|
||||
break
|
||||
}
|
||||
}
|
||||
return lineStart, lineEnd
|
||||
}
|
||||
|
||||
type clone struct {
|
||||
filename string
|
||||
lineStart int
|
||||
lineEnd int
|
||||
fragment []byte
|
||||
}
|
||||
|
||||
type byNameAndLine []clone
|
||||
|
||||
func (c byNameAndLine) Len() int { return len(c) }
|
||||
|
||||
func (c byNameAndLine) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
|
||||
|
||||
func (c byNameAndLine) Less(i, j int) bool {
|
||||
if c[i].filename == c[j].filename {
|
||||
return c[i].lineStart < c[j].lineStart
|
||||
}
|
||||
return c[i].filename < c[j].filename
|
||||
}
|
Reference in New Issue
Block a user