You've already forked postgres_exporter
mirror of
https://github.com/prometheus-community/postgres_exporter.git
synced 2025-08-09 15:42:47 +03:00
Refactor repository layout and convert build system to Mage.
This commit implements a massive refactor of the repository, and moves the build system over to use Mage (magefile.org) which should allow seamless building across multiple platforms.
This commit is contained in:
42
vendor/github.com/magefile/mage/CONTRIBUTING.md
generated
vendored
Normal file
42
vendor/github.com/magefile/mage/CONTRIBUTING.md
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
# Contributing
|
||||
|
||||
Of course, contributions are more than welcome. Please read these guidelines for
|
||||
making the process as painless as possible.
|
||||
|
||||
## Discussion
|
||||
|
||||
Development discussion should take place on the #mage channel of [gopher
|
||||
slack](https://gophers.slack.com/).
|
||||
|
||||
There is a separate #mage-dev channel that has the github app to post github
|
||||
activity to the channel, to make it easy to follow.
|
||||
|
||||
## Issues
|
||||
|
||||
If there's an issue you'd like to work on, please comment on it, so we can
|
||||
discuss approach, etc. and make sure no one else is currently working on that
|
||||
issue.
|
||||
|
||||
Please always create an issue before sending a PR unless it's an obvious typo
|
||||
or other trivial change.
|
||||
|
||||
## Dependency Management
|
||||
|
||||
Currently mage has no dependencies(!) outside the standard libary. Let's keep
|
||||
it that way. Since it's likely that mage will be vendored into a project,
|
||||
adding dependencies to mage adds dependencies to every project that uses mage.
|
||||
|
||||
## Versions
|
||||
|
||||
Please avoid using features of go and the stdlib that prevent mage from being
|
||||
buildable with older versions of Go. The CI tests currently check that mage is
|
||||
buildable with go 1.7 and later. You may build with whatever version you like,
|
||||
but CI has the final say.
|
||||
|
||||
## Testing
|
||||
|
||||
Please write tests for any new features. Tests must use the normal go testing
|
||||
package.
|
||||
|
||||
Tests must pass the race detector (run `go test -race ./...`).
|
||||
|
9
vendor/github.com/magefile/mage/Gopkg.lock
generated
vendored
Normal file
9
vendor/github.com/magefile/mage/Gopkg.lock
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "ab4fef131ee828e96ba67d31a7d690bd5f2f42040c6766b1b12fe856f87e0ff7"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
22
vendor/github.com/magefile/mage/Gopkg.toml
generated
vendored
Normal file
22
vendor/github.com/magefile/mage/Gopkg.toml
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
|
||||
# Gopkg.toml example
|
||||
#
|
||||
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
|
||||
# for detailed Gopkg.toml documentation.
|
||||
#
|
||||
# required = ["github.com/user/thing/cmd/thing"]
|
||||
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project"
|
||||
# version = "1.0.0"
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project2"
|
||||
# branch = "dev"
|
||||
# source = "github.com/myfork/project2"
|
||||
#
|
||||
# [[override]]
|
||||
# name = "github.com/x/y"
|
||||
# version = "2.4.0"
|
||||
|
201
vendor/github.com/magefile/mage/LICENSE
generated
vendored
Normal file
201
vendor/github.com/magefile/mage/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
61
vendor/github.com/magefile/mage/README.md
generated
vendored
Normal file
61
vendor/github.com/magefile/mage/README.md
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
<p align="center"><img src="https://user-images.githubusercontent.com/3185864/32058716-5ee9b512-ba38-11e7-978a-287eb2a62743.png"/></p>
|
||||
|
||||
## About [](https://travis-ci.org/magefile/mage)
|
||||
|
||||
Mage is a make/rake-like build tool using Go. You write plain-old go functions,
|
||||
and Mage automatically uses them as Makefile-like runnable targets.
|
||||
|
||||
## Installation
|
||||
|
||||
Mage has no dependencies outside the Go standard library, and builds with Go 1.7
|
||||
and above (possibly even lower versions, but they're not regularly tested).
|
||||
|
||||
Install mage by running
|
||||
|
||||
```
|
||||
go get -u -d github.com/magefile/mage
|
||||
cd $GOPATH/src/github.com/magefile/mage
|
||||
go run bootstrap.go
|
||||
```
|
||||
|
||||
This will download the code into your GOPATH, and then run the bootstrap script
|
||||
to build mage with version infomation embedded in it. A normal `go get`
|
||||
(without -d) will build the binary correctly, but no version info will be
|
||||
embedded. If you've done this, no worries, just go to
|
||||
$GOPATH/src/github.com/magefile/mage and run `mage install` or `go run
|
||||
bootstrap.go` and a new binary will be created with the correct version
|
||||
information.
|
||||
|
||||
The mage binary will be created in your $GOPATH/bin directory.
|
||||
|
||||
You may also install a binary release from our
|
||||
[releases](https://github.com/magefile/mage/releases) page.
|
||||
|
||||
## Demo
|
||||
|
||||
[](https://www.youtube.com/watch?v=GOqbD0lF-iA)
|
||||
|
||||
## Discussion
|
||||
|
||||
Join the `#mage` channel on [gophers slack](https://gophers.slack.com/messages/general/) for discussion of usage, development, etc.
|
||||
|
||||
# Documentation
|
||||
|
||||
see [magefile.org](https://magefile.org) for full docs
|
||||
|
||||
see [godoc.org/github.com/magefile/mage/mage](https://godoc.org/github.com/magefile/mage/mage) for how to use mage as a library.
|
||||
|
||||
# Why?
|
||||
|
||||
Makefiles are hard to read and hard to write. Mostly because makefiles are essentially fancy bash scripts with significant white space and additional make-related syntax.
|
||||
|
||||
Mage lets you have multiple magefiles, name your magefiles whatever you
|
||||
want, and they're easy to customize for multiple operating systems. Mage has no
|
||||
dependencies (aside from go) and runs just fine on all major operating systems, whereas make generally uses bash which is not well supported on Windows.
|
||||
Go is superior to bash for any non-trivial task involving branching, looping, anything that's not just straight line execution of commands. And if your project is written in Go, why introduce another
|
||||
language as idiosyncratic as bash? Why not use the language your contributors
|
||||
are already comfortable with?
|
||||
|
||||
# TODO
|
||||
|
||||
* File conversion tasks
|
19
vendor/github.com/magefile/mage/bootstrap.go
generated
vendored
Normal file
19
vendor/github.com/magefile/mage/bootstrap.go
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
//+build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/magefile/mage/mage"
|
||||
)
|
||||
|
||||
// This is a bootstrap builder, to build mage when you don't already *have* mage.
|
||||
// Run it like
|
||||
// go run bootstrap.go
|
||||
// and it will install mage with all the right flags created for you.
|
||||
|
||||
func main() {
|
||||
os.Args = []string{os.Args[0], "-v", "install"}
|
||||
os.Exit(mage.Main())
|
||||
}
|
1655
vendor/github.com/magefile/mage/build/build.go
generated
vendored
Normal file
1655
vendor/github.com/magefile/mage/build/build.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
166
vendor/github.com/magefile/mage/build/doc.go
generated
vendored
Normal file
166
vendor/github.com/magefile/mage/build/doc.go
generated
vendored
Normal file
@@ -0,0 +1,166 @@
|
||||
// Copyright 2011 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 build gathers information about Go packages.
|
||||
//
|
||||
// Go Path
|
||||
//
|
||||
// The Go path is a list of directory trees containing Go source code.
|
||||
// It is consulted to resolve imports that cannot be found in the standard
|
||||
// Go tree. The default path is the value of the GOPATH environment
|
||||
// variable, interpreted as a path list appropriate to the operating system
|
||||
// (on Unix, the variable is a colon-separated string;
|
||||
// on Windows, a semicolon-separated string;
|
||||
// on Plan 9, a list).
|
||||
//
|
||||
// Each directory listed in the Go path must have a prescribed structure:
|
||||
//
|
||||
// The src/ directory holds source code. The path below 'src' determines
|
||||
// the import path or executable name.
|
||||
//
|
||||
// The pkg/ directory holds installed package objects.
|
||||
// As in the Go tree, each target operating system and
|
||||
// architecture pair has its own subdirectory of pkg
|
||||
// (pkg/GOOS_GOARCH).
|
||||
//
|
||||
// If DIR is a directory listed in the Go path, a package with
|
||||
// source in DIR/src/foo/bar can be imported as "foo/bar" and
|
||||
// has its compiled form installed to "DIR/pkg/GOOS_GOARCH/foo/bar.a"
|
||||
// (or, for gccgo, "DIR/pkg/gccgo/foo/libbar.a").
|
||||
//
|
||||
// The bin/ directory holds compiled commands.
|
||||
// Each command is named for its source directory, but only
|
||||
// using the final element, not the entire path. That is, the
|
||||
// command with source in DIR/src/foo/quux is installed into
|
||||
// DIR/bin/quux, not DIR/bin/foo/quux. The foo/ is stripped
|
||||
// so that you can add DIR/bin to your PATH to get at the
|
||||
// installed commands.
|
||||
//
|
||||
// Here's an example directory layout:
|
||||
//
|
||||
// GOPATH=/home/user/gocode
|
||||
//
|
||||
// /home/user/gocode/
|
||||
// src/
|
||||
// foo/
|
||||
// bar/ (go code in package bar)
|
||||
// x.go
|
||||
// quux/ (go code in package main)
|
||||
// y.go
|
||||
// bin/
|
||||
// quux (installed command)
|
||||
// pkg/
|
||||
// linux_amd64/
|
||||
// foo/
|
||||
// bar.a (installed package object)
|
||||
//
|
||||
// Build Constraints
|
||||
//
|
||||
// A build constraint, also known as a build tag, is a line comment that begins
|
||||
//
|
||||
// // +build
|
||||
//
|
||||
// that lists the conditions under which a file should be included in the package.
|
||||
// Constraints may appear in any kind of source file (not just Go), but
|
||||
// they must appear near the top of the file, preceded
|
||||
// only by blank lines and other line comments. These rules mean that in Go
|
||||
// files a build constraint must appear before the package clause.
|
||||
//
|
||||
// To distinguish build constraints from package documentation, a series of
|
||||
// build constraints must be followed by a blank line.
|
||||
//
|
||||
// A build constraint is evaluated as the OR of space-separated options;
|
||||
// each option evaluates as the AND of its comma-separated terms;
|
||||
// and each term is an alphanumeric word or, preceded by !, its negation.
|
||||
// That is, the build constraint:
|
||||
//
|
||||
// // +build linux,386 darwin,!cgo
|
||||
//
|
||||
// corresponds to the boolean formula:
|
||||
//
|
||||
// (linux AND 386) OR (darwin AND (NOT cgo))
|
||||
//
|
||||
// A file may have multiple build constraints. The overall constraint is the AND
|
||||
// of the individual constraints. That is, the build constraints:
|
||||
//
|
||||
// // +build linux darwin
|
||||
// // +build 386
|
||||
//
|
||||
// corresponds to the boolean formula:
|
||||
//
|
||||
// (linux OR darwin) AND 386
|
||||
//
|
||||
// During a particular build, the following words are satisfied:
|
||||
//
|
||||
// - the target operating system, as spelled by runtime.GOOS
|
||||
// - the target architecture, as spelled by runtime.GOARCH
|
||||
// - the compiler being used, either "gc" or "gccgo"
|
||||
// - "cgo", if ctxt.CgoEnabled is true
|
||||
// - "go1.1", from Go version 1.1 onward
|
||||
// - "go1.2", from Go version 1.2 onward
|
||||
// - "go1.3", from Go version 1.3 onward
|
||||
// - "go1.4", from Go version 1.4 onward
|
||||
// - "go1.5", from Go version 1.5 onward
|
||||
// - "go1.6", from Go version 1.6 onward
|
||||
// - "go1.7", from Go version 1.7 onward
|
||||
// - "go1.8", from Go version 1.8 onward
|
||||
// - "go1.9", from Go version 1.9 onward
|
||||
// - any additional words listed in ctxt.BuildTags
|
||||
//
|
||||
// If a file's name, after stripping the extension and a possible _test suffix,
|
||||
// matches any of the following patterns:
|
||||
// *_GOOS
|
||||
// *_GOARCH
|
||||
// *_GOOS_GOARCH
|
||||
// (example: source_windows_amd64.go) where GOOS and GOARCH represent
|
||||
// any known operating system and architecture values respectively, then
|
||||
// the file is considered to have an implicit build constraint requiring
|
||||
// those terms (in addition to any explicit constraints in the file).
|
||||
//
|
||||
// To keep a file from being considered for the build:
|
||||
//
|
||||
// // +build ignore
|
||||
//
|
||||
// (any other unsatisfied word will work as well, but ``ignore'' is conventional.)
|
||||
//
|
||||
// To build a file only when using cgo, and only on Linux and OS X:
|
||||
//
|
||||
// // +build linux,cgo darwin,cgo
|
||||
//
|
||||
// Such a file is usually paired with another file implementing the
|
||||
// default functionality for other systems, which in this case would
|
||||
// carry the constraint:
|
||||
//
|
||||
// // +build !linux,!darwin !cgo
|
||||
//
|
||||
// Naming a file dns_windows.go will cause it to be included only when
|
||||
// building the package for Windows; similarly, math_386.s will be included
|
||||
// only when building the package for 32-bit x86.
|
||||
//
|
||||
// Using GOOS=android matches build tags and files as for GOOS=linux
|
||||
// in addition to android tags and files.
|
||||
//
|
||||
// Binary-Only Packages
|
||||
//
|
||||
// It is possible to distribute packages in binary form without including the
|
||||
// source code used for compiling the package. To do this, the package must
|
||||
// be distributed with a source file not excluded by build constraints and
|
||||
// containing a "//go:binary-only-package" comment.
|
||||
// Like a build constraint, this comment must appear near the top of the file,
|
||||
// preceded only by blank lines and other line comments and with a blank line
|
||||
// following the comment, to separate it from the package documentation.
|
||||
// Unlike build constraints, this comment is only recognized in non-test
|
||||
// Go source files.
|
||||
//
|
||||
// The minimal source code for a binary-only package is therefore:
|
||||
//
|
||||
// //go:binary-only-package
|
||||
//
|
||||
// package mypkg
|
||||
//
|
||||
// The source code may include additional Go code. That code is never compiled
|
||||
// but will be processed by tools like godoc and might be useful as end-user
|
||||
// documentation.
|
||||
//
|
||||
package build
|
247
vendor/github.com/magefile/mage/build/read.go
generated
vendored
Normal file
247
vendor/github.com/magefile/mage/build/read.go
generated
vendored
Normal file
@@ -0,0 +1,247 @@
|
||||
// Copyright 2012 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 build
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"io"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
type importReader struct {
|
||||
b *bufio.Reader
|
||||
buf []byte
|
||||
peek byte
|
||||
err error
|
||||
eof bool
|
||||
nerr int
|
||||
}
|
||||
|
||||
func isIdent(c byte) bool {
|
||||
return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' || c == '_' || c >= utf8.RuneSelf
|
||||
}
|
||||
|
||||
var (
|
||||
errSyntax = errors.New("syntax error")
|
||||
errNUL = errors.New("unexpected NUL in input")
|
||||
)
|
||||
|
||||
// syntaxError records a syntax error, but only if an I/O error has not already been recorded.
|
||||
func (r *importReader) syntaxError() {
|
||||
if r.err == nil {
|
||||
r.err = errSyntax
|
||||
}
|
||||
}
|
||||
|
||||
// readByte reads the next byte from the input, saves it in buf, and returns it.
|
||||
// If an error occurs, readByte records the error in r.err and returns 0.
|
||||
func (r *importReader) readByte() byte {
|
||||
c, err := r.b.ReadByte()
|
||||
if err == nil {
|
||||
r.buf = append(r.buf, c)
|
||||
if c == 0 {
|
||||
err = errNUL
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
r.eof = true
|
||||
} else if r.err == nil {
|
||||
r.err = err
|
||||
}
|
||||
c = 0
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// peekByte returns the next byte from the input reader but does not advance beyond it.
|
||||
// If skipSpace is set, peekByte skips leading spaces and comments.
|
||||
func (r *importReader) peekByte(skipSpace bool) byte {
|
||||
if r.err != nil {
|
||||
if r.nerr++; r.nerr > 10000 {
|
||||
panic("go/build: import reader looping")
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Use r.peek as first input byte.
|
||||
// Don't just return r.peek here: it might have been left by peekByte(false)
|
||||
// and this might be peekByte(true).
|
||||
c := r.peek
|
||||
if c == 0 {
|
||||
c = r.readByte()
|
||||
}
|
||||
for r.err == nil && !r.eof {
|
||||
if skipSpace {
|
||||
// For the purposes of this reader, semicolons are never necessary to
|
||||
// understand the input and are treated as spaces.
|
||||
switch c {
|
||||
case ' ', '\f', '\t', '\r', '\n', ';':
|
||||
c = r.readByte()
|
||||
continue
|
||||
|
||||
case '/':
|
||||
c = r.readByte()
|
||||
if c == '/' {
|
||||
for c != '\n' && r.err == nil && !r.eof {
|
||||
c = r.readByte()
|
||||
}
|
||||
} else if c == '*' {
|
||||
var c1 byte
|
||||
for (c != '*' || c1 != '/') && r.err == nil {
|
||||
if r.eof {
|
||||
r.syntaxError()
|
||||
}
|
||||
c, c1 = c1, r.readByte()
|
||||
}
|
||||
} else {
|
||||
r.syntaxError()
|
||||
}
|
||||
c = r.readByte()
|
||||
continue
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
r.peek = c
|
||||
return r.peek
|
||||
}
|
||||
|
||||
// nextByte is like peekByte but advances beyond the returned byte.
|
||||
func (r *importReader) nextByte(skipSpace bool) byte {
|
||||
c := r.peekByte(skipSpace)
|
||||
r.peek = 0
|
||||
return c
|
||||
}
|
||||
|
||||
// readKeyword reads the given keyword from the input.
|
||||
// If the keyword is not present, readKeyword records a syntax error.
|
||||
func (r *importReader) readKeyword(kw string) {
|
||||
r.peekByte(true)
|
||||
for i := 0; i < len(kw); i++ {
|
||||
if r.nextByte(false) != kw[i] {
|
||||
r.syntaxError()
|
||||
return
|
||||
}
|
||||
}
|
||||
if isIdent(r.peekByte(false)) {
|
||||
r.syntaxError()
|
||||
}
|
||||
}
|
||||
|
||||
// readIdent reads an identifier from the input.
|
||||
// If an identifier is not present, readIdent records a syntax error.
|
||||
func (r *importReader) readIdent() {
|
||||
c := r.peekByte(true)
|
||||
if !isIdent(c) {
|
||||
r.syntaxError()
|
||||
return
|
||||
}
|
||||
for isIdent(r.peekByte(false)) {
|
||||
r.peek = 0
|
||||
}
|
||||
}
|
||||
|
||||
// readString reads a quoted string literal from the input.
|
||||
// If an identifier is not present, readString records a syntax error.
|
||||
func (r *importReader) readString(save *[]string) {
|
||||
switch r.nextByte(true) {
|
||||
case '`':
|
||||
start := len(r.buf) - 1
|
||||
for r.err == nil {
|
||||
if r.nextByte(false) == '`' {
|
||||
if save != nil {
|
||||
*save = append(*save, string(r.buf[start:]))
|
||||
}
|
||||
break
|
||||
}
|
||||
if r.eof {
|
||||
r.syntaxError()
|
||||
}
|
||||
}
|
||||
case '"':
|
||||
start := len(r.buf) - 1
|
||||
for r.err == nil {
|
||||
c := r.nextByte(false)
|
||||
if c == '"' {
|
||||
if save != nil {
|
||||
*save = append(*save, string(r.buf[start:]))
|
||||
}
|
||||
break
|
||||
}
|
||||
if r.eof || c == '\n' {
|
||||
r.syntaxError()
|
||||
}
|
||||
if c == '\\' {
|
||||
r.nextByte(false)
|
||||
}
|
||||
}
|
||||
default:
|
||||
r.syntaxError()
|
||||
}
|
||||
}
|
||||
|
||||
// readImport reads an import clause - optional identifier followed by quoted string -
|
||||
// from the input.
|
||||
func (r *importReader) readImport(imports *[]string) {
|
||||
c := r.peekByte(true)
|
||||
if c == '.' {
|
||||
r.peek = 0
|
||||
} else if isIdent(c) {
|
||||
r.readIdent()
|
||||
}
|
||||
r.readString(imports)
|
||||
}
|
||||
|
||||
// readComments is like ioutil.ReadAll, except that it only reads the leading
|
||||
// block of comments in the file.
|
||||
func readComments(f io.Reader) ([]byte, error) {
|
||||
r := &importReader{b: bufio.NewReader(f)}
|
||||
r.peekByte(true)
|
||||
if r.err == nil && !r.eof {
|
||||
// Didn't reach EOF, so must have found a non-space byte. Remove it.
|
||||
r.buf = r.buf[:len(r.buf)-1]
|
||||
}
|
||||
return r.buf, r.err
|
||||
}
|
||||
|
||||
// readImports is like ioutil.ReadAll, except that it expects a Go file as input
|
||||
// and stops reading the input once the imports have completed.
|
||||
func readImports(f io.Reader, reportSyntaxError bool, imports *[]string) ([]byte, error) {
|
||||
r := &importReader{b: bufio.NewReader(f)}
|
||||
|
||||
r.readKeyword("package")
|
||||
r.readIdent()
|
||||
for r.peekByte(true) == 'i' {
|
||||
r.readKeyword("import")
|
||||
if r.peekByte(true) == '(' {
|
||||
r.nextByte(false)
|
||||
for r.peekByte(true) != ')' && r.err == nil {
|
||||
r.readImport(imports)
|
||||
}
|
||||
r.nextByte(false)
|
||||
} else {
|
||||
r.readImport(imports)
|
||||
}
|
||||
}
|
||||
|
||||
// If we stopped successfully before EOF, we read a byte that told us we were done.
|
||||
// Return all but that last byte, which would cause a syntax error if we let it through.
|
||||
if r.err == nil && !r.eof {
|
||||
return r.buf[:len(r.buf)-1], nil
|
||||
}
|
||||
|
||||
// If we stopped for a syntax error, consume the whole file so that
|
||||
// we are sure we don't change the errors that go/parser returns.
|
||||
if r.err == errSyntax && !reportSyntaxError {
|
||||
r.err = nil
|
||||
for r.err == nil && !r.eof {
|
||||
r.readByte()
|
||||
}
|
||||
}
|
||||
|
||||
return r.buf, r.err
|
||||
}
|
8
vendor/github.com/magefile/mage/build/syslist.go
generated
vendored
Normal file
8
vendor/github.com/magefile/mage/build/syslist.go
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
// Copyright 2011 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 build
|
||||
|
||||
const goosList = "android darwin dragonfly freebsd linux nacl netbsd openbsd plan9 solaris windows zos "
|
||||
const goarchList = "386 amd64 amd64p32 arm armbe arm64 arm64be ppc64 ppc64le mips mipsle mips64 mips64le mips64p32 mips64p32le ppc s390 s390x sparc sparc64 "
|
37
vendor/github.com/magefile/mage/build/zcgo.go
generated
vendored
Normal file
37
vendor/github.com/magefile/mage/build/zcgo.go
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
// auto generated by go tool dist
|
||||
|
||||
package build
|
||||
|
||||
const defaultCGO_ENABLED = ""
|
||||
|
||||
var cgoEnabled = map[string]bool{
|
||||
"android/386": true,
|
||||
"android/amd64": true,
|
||||
"android/arm": true,
|
||||
"android/arm64": true,
|
||||
"darwin/386": true,
|
||||
"darwin/amd64": true,
|
||||
"darwin/arm": true,
|
||||
"darwin/arm64": true,
|
||||
"dragonfly/amd64": true,
|
||||
"freebsd/386": true,
|
||||
"freebsd/amd64": true,
|
||||
"linux/386": true,
|
||||
"linux/amd64": true,
|
||||
"linux/arm": true,
|
||||
"linux/arm64": true,
|
||||
"linux/mips": true,
|
||||
"linux/mips64": true,
|
||||
"linux/mips64le": true,
|
||||
"linux/mipsle": true,
|
||||
"linux/ppc64le": true,
|
||||
"linux/s390x": true,
|
||||
"netbsd/386": true,
|
||||
"netbsd/amd64": true,
|
||||
"netbsd/arm": true,
|
||||
"openbsd/386": true,
|
||||
"openbsd/amd64": true,
|
||||
"solaris/amd64": true,
|
||||
"windows/386": true,
|
||||
"windows/amd64": true,
|
||||
}
|
16
vendor/github.com/magefile/mage/mage/command_string.go
generated
vendored
Normal file
16
vendor/github.com/magefile/mage/mage/command_string.go
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
// Code generated by "stringer -type=Command"; DO NOT EDIT.
|
||||
|
||||
package mage
|
||||
|
||||
import "fmt"
|
||||
|
||||
const _Command_name = "NoneVersionInitClean"
|
||||
|
||||
var _Command_index = [...]uint8{0, 4, 11, 15, 20}
|
||||
|
||||
func (i Command) String() string {
|
||||
if i < 0 || i >= Command(len(_Command_index)-1) {
|
||||
return fmt.Sprintf("Command(%d)", i)
|
||||
}
|
||||
return _Command_name[_Command_index[i]:_Command_index[i+1]]
|
||||
}
|
46
vendor/github.com/magefile/mage/mage/magefile_tmpl.go
generated
vendored
Normal file
46
vendor/github.com/magefile/mage/mage/magefile_tmpl.go
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
package mage
|
||||
|
||||
var mageTpl = `// +build mage
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/magefile/mage/mg" // mg contains helpful utility functions, like Deps
|
||||
)
|
||||
|
||||
// Default target to run when none is specified
|
||||
// If not set, running mage will list available targets
|
||||
// var Default = Build
|
||||
|
||||
// A build step that requires additional params, or platform specific steps for example
|
||||
func Build() error {
|
||||
mg.Deps(InstallDeps)
|
||||
fmt.Println("Building...")
|
||||
cmd := exec.Command("go", "build", "-o", "MyApp", ".")
|
||||
return cmd.Run()
|
||||
}
|
||||
|
||||
// A custom install step if you need your bin someplace other than go/bin
|
||||
func Install() error {
|
||||
mg.Deps(Build)
|
||||
fmt.Println("Installing...")
|
||||
return os.Rename("./MyApp", "/usr/bin/MyApp")
|
||||
}
|
||||
|
||||
// Manage your deps, or running package managers.
|
||||
func InstallDeps() error {
|
||||
fmt.Println("Installing Deps...")
|
||||
cmd := exec.Command("go", "get", "github.com/stretchr/piglatin")
|
||||
return cmd.Run()
|
||||
}
|
||||
|
||||
// Clean up after yourself
|
||||
func Clean() {
|
||||
fmt.Println("Cleaning...")
|
||||
os.RemoveAll("MyApp")
|
||||
}
|
||||
`
|
459
vendor/github.com/magefile/mage/mage/main.go
generated
vendored
Normal file
459
vendor/github.com/magefile/mage/mage/main.go
generated
vendored
Normal file
@@ -0,0 +1,459 @@
|
||||
package mage
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/template"
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
"github.com/magefile/mage/build"
|
||||
"github.com/magefile/mage/mg"
|
||||
"github.com/magefile/mage/parse"
|
||||
"github.com/magefile/mage/sh"
|
||||
)
|
||||
|
||||
// magicRebuildKey is used when hashing the output binary to ensure that we get
|
||||
// a new binary even if nothing in the input files or generated mainfile has
|
||||
// changed. This can be used when we change how we parse files, or otherwise
|
||||
// change the inputs to the compiling process.
|
||||
const magicRebuildKey = "v0.3"
|
||||
|
||||
var output = template.Must(template.New("").Funcs(map[string]interface{}{
|
||||
"lower": strings.ToLower,
|
||||
"lowerfirst": func(s string) string {
|
||||
r := []rune(s)
|
||||
return string(unicode.ToLower(r[0])) + string(r[1:])
|
||||
},
|
||||
}).Parse(tpl))
|
||||
var initOutput = template.Must(template.New("").Parse(mageTpl))
|
||||
|
||||
const mainfile = "mage_output_file.go"
|
||||
const initFile = "magefile.go"
|
||||
|
||||
// set by ldflags when you "mage build"
|
||||
var (
|
||||
commitHash string
|
||||
timestamp string
|
||||
gitTag = "v2"
|
||||
)
|
||||
|
||||
//go:generate stringer -type=Command
|
||||
|
||||
// Command tracks invocations of mage that run without targets or other flags.
|
||||
type Command int
|
||||
|
||||
const (
|
||||
None Command = iota
|
||||
Version // report the current version of mage
|
||||
Init // create a starting template for mage
|
||||
Clean // clean out old compiled mage binaries from the cache
|
||||
)
|
||||
|
||||
// Main is the entrypoint for running mage. It exists external to mage's main
|
||||
// function to allow it to be used from other programs, specifically so you can
|
||||
// go run a simple file that run's mage's Main.
|
||||
func Main() int {
|
||||
return ParseAndRun(".", os.Stdout, os.Stderr, os.Stdin, os.Args[1:])
|
||||
}
|
||||
|
||||
// Invocation contains the args for invoking a run of Mage.
|
||||
type Invocation struct {
|
||||
Dir string // directory to read magefiles from
|
||||
Force bool // forces recreation of the compiled binary
|
||||
Verbose bool // tells the magefile to print out log statements
|
||||
List bool // tells the magefile to print out a list of targets
|
||||
Help bool // tells the magefile to print out help for a specific target
|
||||
Keep bool // tells mage to keep the generated main file after compiling
|
||||
Timeout time.Duration // tells mage to set a timeout to running the targets
|
||||
Stdout io.Writer // writer to write stdout messages to
|
||||
Stderr io.Writer // writer to write stderr messages to
|
||||
Stdin io.Reader // reader to read stdin from
|
||||
Args []string // args to pass to the compiled binary
|
||||
}
|
||||
|
||||
// ParseAndRun parses the command line, and then compiles and runs the mage
|
||||
// files in the given directory with the given args (do not include the command
|
||||
// name in the args).
|
||||
func ParseAndRun(dir string, stdout, stderr io.Writer, stdin io.Reader, args []string) int {
|
||||
log := log.New(stderr, "", 0)
|
||||
inv, cmd, err := Parse(stdout, args)
|
||||
inv.Dir = dir
|
||||
inv.Stderr = stderr
|
||||
inv.Stdin = stdin
|
||||
if err == flag.ErrHelp {
|
||||
return 0
|
||||
}
|
||||
if err != nil {
|
||||
log.Println("Error:", err)
|
||||
return 2
|
||||
}
|
||||
|
||||
switch cmd {
|
||||
case Version:
|
||||
if timestamp == "" {
|
||||
timestamp = "<not set>"
|
||||
}
|
||||
if commitHash == "" {
|
||||
commitHash = "<not set>"
|
||||
}
|
||||
log.Println("Mage Build Tool", gitTag)
|
||||
log.Println("Build Date:", timestamp)
|
||||
log.Println("Commit:", commitHash)
|
||||
return 0
|
||||
case Init:
|
||||
if err := generateInit(dir); err != nil {
|
||||
log.Println("Error:", err)
|
||||
return 1
|
||||
}
|
||||
log.Println(initFile, "created")
|
||||
return 0
|
||||
case Clean:
|
||||
dir := mg.CacheDir()
|
||||
if err := removeContents(dir); err != nil {
|
||||
log.Println("Error:", err)
|
||||
return 1
|
||||
}
|
||||
log.Println(dir, "cleaned")
|
||||
return 0
|
||||
case None:
|
||||
return Invoke(inv)
|
||||
default:
|
||||
panic(fmt.Errorf("Unknown command type: %v", cmd))
|
||||
}
|
||||
}
|
||||
|
||||
// Parse parses the given args and returns structured data. If parse returns
|
||||
// flag.ErrHelp, the calling process should exit with code 0.
|
||||
func Parse(stdout io.Writer, args []string) (inv Invocation, cmd Command, err error) {
|
||||
inv.Stdout = stdout
|
||||
fs := flag.FlagSet{}
|
||||
fs.SetOutput(stdout)
|
||||
fs.BoolVar(&inv.Force, "f", false, "force recreation of compiled magefile")
|
||||
fs.BoolVar(&inv.Verbose, "v", false, "show verbose output when running mage targets")
|
||||
fs.BoolVar(&inv.List, "l", false, "list mage targets in this directory")
|
||||
fs.BoolVar(&inv.Help, "h", false, "show this help")
|
||||
fs.DurationVar(&inv.Timeout, "t", 0, "timeout in duration parsable format (e.g. 5m30s)")
|
||||
fs.BoolVar(&inv.Keep, "keep", false, "keep intermediate mage files around after running")
|
||||
var showVersion bool
|
||||
fs.BoolVar(&showVersion, "version", false, "show version info for the mage binary")
|
||||
var mageInit bool
|
||||
fs.BoolVar(&mageInit, "init", false, "create a starting template if no mage files exist")
|
||||
var clean bool
|
||||
fs.BoolVar(&clean, "clean", false, "clean out old generated binaries from CACHE_DIR")
|
||||
|
||||
fs.Usage = func() {
|
||||
fmt.Fprintln(stdout, "mage [options] [target]")
|
||||
fmt.Fprintln(stdout, "Options:")
|
||||
fs.PrintDefaults()
|
||||
}
|
||||
err = fs.Parse(args)
|
||||
if err == flag.ErrHelp {
|
||||
// parse will have already called fs.Usage()
|
||||
return inv, cmd, err
|
||||
}
|
||||
if err == nil && inv.Help && len(fs.Args()) == 0 {
|
||||
fs.Usage()
|
||||
// tell upstream, to just exit
|
||||
return inv, cmd, flag.ErrHelp
|
||||
}
|
||||
|
||||
numFlags := 0
|
||||
switch {
|
||||
case mageInit:
|
||||
numFlags++
|
||||
cmd = Init
|
||||
case showVersion:
|
||||
numFlags++
|
||||
cmd = Version
|
||||
case clean:
|
||||
numFlags++
|
||||
cmd = Clean
|
||||
if fs.NArg() > 0 || fs.NFlag() > 1 {
|
||||
// Temporary dupe of below check until we refactor the other commands to use this check
|
||||
return inv, cmd, errors.New("-h, -init, -clean, and -version cannot be used simultaneously")
|
||||
|
||||
}
|
||||
}
|
||||
if inv.Help {
|
||||
numFlags++
|
||||
}
|
||||
|
||||
// If verbose is still false, we're going to peek at the environment variable to see if
|
||||
// MAGE_VERBOSE has been set. If so, we're going to use it for the value of MAGE_VERBOSE.
|
||||
if inv.Verbose == false {
|
||||
envVerbose, err := strconv.ParseBool(os.Getenv("MAGE_VERBOSE"))
|
||||
if err == nil {
|
||||
inv.Verbose = envVerbose
|
||||
}
|
||||
}
|
||||
|
||||
if numFlags > 1 {
|
||||
return inv, cmd, errors.New("-h, -init, -clean, and -version cannot be used simultaneously")
|
||||
}
|
||||
|
||||
inv.Args = fs.Args()
|
||||
if inv.Help && len(inv.Args) > 1 {
|
||||
return inv, cmd, errors.New("-h can only show help for a single target")
|
||||
}
|
||||
|
||||
return inv, cmd, err
|
||||
}
|
||||
|
||||
// Invoke runs Mage with the given arguments.
|
||||
func Invoke(inv Invocation) int {
|
||||
log := log.New(inv.Stderr, "", 0)
|
||||
|
||||
files, err := Magefiles(inv.Dir)
|
||||
if err != nil {
|
||||
log.Println("Error:", err)
|
||||
return 1
|
||||
}
|
||||
|
||||
if len(files) == 0 {
|
||||
log.Println("No .go files marked with the mage build tag in this directory.")
|
||||
return 1
|
||||
}
|
||||
|
||||
exePath, err := ExeName(files)
|
||||
|
||||
if err != nil {
|
||||
log.Println("Error:", err)
|
||||
return 1
|
||||
}
|
||||
|
||||
if !inv.Force {
|
||||
if _, err := os.Stat(exePath); err == nil {
|
||||
return RunCompiled(inv, exePath)
|
||||
}
|
||||
}
|
||||
|
||||
// parse wants dir + filenames... arg
|
||||
fnames := make([]string, 0, len(files))
|
||||
for i := range files {
|
||||
fnames = append(fnames, filepath.Base(files[i]))
|
||||
}
|
||||
|
||||
info, err := parse.Package(inv.Dir, fnames)
|
||||
if err != nil {
|
||||
log.Println("Error:", err)
|
||||
return 1
|
||||
}
|
||||
|
||||
hasDupes, names := CheckDupes(info)
|
||||
if hasDupes {
|
||||
log.Println("Build targets must be case insensitive, thus the follow targets conflict:")
|
||||
for _, v := range names {
|
||||
if len(v) > 1 {
|
||||
log.Println(" " + strings.Join(v, ", "))
|
||||
}
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
main := filepath.Join(inv.Dir, mainfile)
|
||||
if err := GenerateMainfile(main, info); err != nil {
|
||||
log.Println("Error:", err)
|
||||
return 1
|
||||
}
|
||||
if !inv.Keep {
|
||||
defer os.Remove(main)
|
||||
}
|
||||
files = append(files, main)
|
||||
if err := Compile(exePath, inv.Stdout, inv.Stderr, files); err != nil {
|
||||
log.Println("Error:", err)
|
||||
return 1
|
||||
}
|
||||
if !inv.Keep {
|
||||
// remove this file before we run the compiled version, in case the
|
||||
// compiled file screws things up. Yes this doubles up with the above
|
||||
// defer, that's ok.
|
||||
os.Remove(main)
|
||||
}
|
||||
|
||||
return RunCompiled(inv, exePath)
|
||||
}
|
||||
|
||||
// CheckDupes checks a package for duplicate target names.
|
||||
func CheckDupes(info *parse.PkgInfo) (hasDupes bool, names map[string][]string) {
|
||||
names = map[string][]string{}
|
||||
lowers := map[string]bool{}
|
||||
for _, f := range info.Funcs {
|
||||
low := strings.ToLower(f.Name)
|
||||
if lowers[low] {
|
||||
hasDupes = true
|
||||
}
|
||||
lowers[low] = true
|
||||
names[low] = append(names[low], f.Name)
|
||||
}
|
||||
return hasDupes, names
|
||||
}
|
||||
|
||||
type data struct {
|
||||
Funcs []parse.Function
|
||||
DefaultError bool
|
||||
Default string
|
||||
DefaultFunc parse.Function
|
||||
Aliases map[string]string
|
||||
}
|
||||
|
||||
// Magefiles returns the list of magefiles in dir.
|
||||
func Magefiles(dir string) ([]string, error) {
|
||||
ctx := build.Default
|
||||
ctx.RequiredTags = []string{"mage"}
|
||||
ctx.BuildTags = []string{"mage"}
|
||||
p, err := ctx.ImportDir(dir, 0)
|
||||
if err != nil {
|
||||
if _, ok := err.(*build.NoGoError); ok {
|
||||
return []string{}, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
for i := range p.GoFiles {
|
||||
p.GoFiles[i] = filepath.Join(dir, p.GoFiles[i])
|
||||
}
|
||||
return p.GoFiles, nil
|
||||
}
|
||||
|
||||
// Compile uses the go tool to compile the files into an executable at path.
|
||||
func Compile(path string, stdout, stderr io.Writer, gofiles []string) error {
|
||||
c := exec.Command("go", append([]string{"build", "-o", path}, gofiles...)...)
|
||||
c.Env = os.Environ()
|
||||
c.Stderr = stderr
|
||||
c.Stdout = stdout
|
||||
err := c.Run()
|
||||
if err != nil {
|
||||
return errors.New("error compiling magefiles")
|
||||
}
|
||||
if _, err := os.Stat(path); err != nil {
|
||||
return errors.New("failed to find compiled magefile")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GenerateMainfile creates the mainfile at path with the info from
|
||||
func GenerateMainfile(path string, info *parse.PkgInfo) error {
|
||||
f, err := os.Create(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't create mainfile: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
data := data{
|
||||
Funcs: info.Funcs,
|
||||
Default: info.DefaultName,
|
||||
DefaultFunc: info.DefaultFunc,
|
||||
Aliases: info.Aliases,
|
||||
}
|
||||
|
||||
data.DefaultError = info.DefaultIsError
|
||||
|
||||
if err := output.Execute(f, data); err != nil {
|
||||
return fmt.Errorf("can't execute mainfile template: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ExeName reports the executable filename that this version of Mage would
|
||||
// create for the given magefiles.
|
||||
func ExeName(files []string) (string, error) {
|
||||
var hashes []string
|
||||
for _, s := range files {
|
||||
h, err := hashFile(s)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
hashes = append(hashes, h)
|
||||
}
|
||||
// hash the mainfile template to ensure if it gets updated, we make a new
|
||||
// binary.
|
||||
hashes = append(hashes, fmt.Sprintf("%x", sha1.Sum([]byte(tpl))))
|
||||
sort.Strings(hashes)
|
||||
hash := sha1.Sum([]byte(strings.Join(hashes, "") + magicRebuildKey))
|
||||
filename := fmt.Sprintf("%x", hash)
|
||||
|
||||
out := filepath.Join(mg.CacheDir(), filename)
|
||||
if runtime.GOOS == "windows" {
|
||||
out += ".exe"
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func hashFile(fn string) (string, error) {
|
||||
f, err := os.Open(fn)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("can't open input file: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
h := sha1.New()
|
||||
if _, err := io.Copy(h, f); err != nil {
|
||||
return "", fmt.Errorf("can't write data to hash: %v", err)
|
||||
}
|
||||
return fmt.Sprintf("%x", h.Sum(nil)), nil
|
||||
}
|
||||
|
||||
func generateInit(dir string) error {
|
||||
f, err := os.Create(filepath.Join(dir, initFile))
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not create mage template: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
if err := initOutput.Execute(f, nil); err != nil {
|
||||
return fmt.Errorf("can't execute magefile template: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RunCompiled runs an already-compiled mage command with the given args,
|
||||
func RunCompiled(inv Invocation, exePath string) int {
|
||||
c := exec.Command(exePath, inv.Args...)
|
||||
c.Stderr = inv.Stderr
|
||||
c.Stdout = inv.Stdout
|
||||
c.Stdin = inv.Stdin
|
||||
c.Env = os.Environ()
|
||||
if inv.Verbose {
|
||||
c.Env = append(c.Env, "MAGEFILE_VERBOSE=1")
|
||||
}
|
||||
if inv.List {
|
||||
c.Env = append(c.Env, "MAGEFILE_LIST=1")
|
||||
}
|
||||
if inv.Help {
|
||||
c.Env = append(c.Env, "MAGEFILE_HELP=1")
|
||||
}
|
||||
if inv.Timeout > 0 {
|
||||
c.Env = append(c.Env, fmt.Sprintf("MAGEFILE_TIMEOUT=%s", inv.Timeout.String()))
|
||||
}
|
||||
return sh.ExitStatus(c.Run())
|
||||
}
|
||||
|
||||
func removeContents(dir string) error {
|
||||
files, err := ioutil.ReadDir(dir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, f := range files {
|
||||
if f.IsDir() {
|
||||
continue
|
||||
}
|
||||
err = os.Remove(filepath.Join(dir, f.Name()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
202
vendor/github.com/magefile/mage/mage/template.go
generated
vendored
Normal file
202
vendor/github.com/magefile/mage/mage/template.go
generated
vendored
Normal file
@@ -0,0 +1,202 @@
|
||||
package mage
|
||||
|
||||
// var only for tests
|
||||
var tpl = `// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// These functions are local variables to avoid name conflicts with
|
||||
// magefiles.
|
||||
list := func() error {
|
||||
{{- $default := .Default}}
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 4, 4, ' ', 0)
|
||||
fmt.Println("Targets:")
|
||||
{{- range .Funcs}}
|
||||
fmt.Fprintln(w, " {{lowerfirst .Name}}{{if eq .Name $default}}*{{end}}\t" + {{printf "%q" .Synopsis}})
|
||||
{{- end}}
|
||||
err := w.Flush()
|
||||
{{- if .Default}}
|
||||
if err == nil {
|
||||
fmt.Println("\n* default target")
|
||||
}
|
||||
{{- end}}
|
||||
return err
|
||||
}
|
||||
|
||||
var ctx context.Context
|
||||
var ctxCancel func()
|
||||
|
||||
getContext := func() (context.Context, func()) {
|
||||
if ctx != nil {
|
||||
return ctx, ctxCancel
|
||||
}
|
||||
|
||||
if os.Getenv("MAGEFILE_TIMEOUT") != "" {
|
||||
timeout, err := time.ParseDuration(os.Getenv("MAGEFILE_TIMEOUT"))
|
||||
if err != nil {
|
||||
fmt.Printf("timeout error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
ctx, ctxCancel = context.WithTimeout(context.Background(), timeout)
|
||||
} else {
|
||||
ctx = context.Background()
|
||||
ctxCancel = func() {}
|
||||
}
|
||||
return ctx, ctxCancel
|
||||
}
|
||||
|
||||
runTarget := func(fn func(context.Context) error) interface{} {
|
||||
var err interface{}
|
||||
ctx, cancel := getContext()
|
||||
d := make(chan interface{})
|
||||
go func() {
|
||||
defer func() {
|
||||
err := recover()
|
||||
d <- err
|
||||
}()
|
||||
err := fn(ctx)
|
||||
d <- err
|
||||
}()
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
cancel()
|
||||
e := ctx.Err()
|
||||
fmt.Printf("ctx err: %v\n", e)
|
||||
return e
|
||||
case err = <-d:
|
||||
cancel()
|
||||
return err
|
||||
}
|
||||
}
|
||||
// This is necessary in case there aren't any targets, to avoid an unused
|
||||
// variable error.
|
||||
_ = runTarget
|
||||
|
||||
handleError := func(logger *log.Logger, err interface{}) {
|
||||
if err != nil {
|
||||
logger.Printf("Error: %v\n", err)
|
||||
type code interface {
|
||||
ExitStatus() int
|
||||
}
|
||||
if c, ok := err.(code); ok {
|
||||
os.Exit(c.ExitStatus())
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
_ = handleError
|
||||
|
||||
log.SetFlags(0)
|
||||
if os.Getenv("MAGEFILE_VERBOSE") == "" {
|
||||
log.SetOutput(ioutil.Discard)
|
||||
}
|
||||
logger := log.New(os.Stderr, "", 0)
|
||||
if os.Getenv("MAGEFILE_LIST") != "" {
|
||||
if err := list(); err != nil {
|
||||
log.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
targets := map[string]bool {
|
||||
{{range $alias, $funci := .Aliases}}"{{lower $alias}}": true,
|
||||
{{end}}
|
||||
{{range .Funcs}}"{{lower .Name}}": true,
|
||||
{{end}}
|
||||
}
|
||||
|
||||
var unknown []string
|
||||
for _, arg := range os.Args[1:] {
|
||||
if !targets[strings.ToLower(arg)] {
|
||||
unknown = append(unknown, arg)
|
||||
}
|
||||
}
|
||||
if len(unknown) == 1 {
|
||||
logger.Println("Unknown target specified:", unknown[0])
|
||||
os.Exit(2)
|
||||
}
|
||||
if len(unknown) > 1 {
|
||||
logger.Println("Unknown targets specified:", strings.Join(unknown, ", "))
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
if os.Getenv("MAGEFILE_HELP") != "" {
|
||||
if len(os.Args) < 2 {
|
||||
logger.Println("no target specified")
|
||||
os.Exit(1)
|
||||
}
|
||||
switch strings.ToLower(os.Args[1]) {
|
||||
{{range .Funcs}}case "{{lower .Name}}":
|
||||
fmt.Print("mage {{lower .Name}}:\n\n")
|
||||
{{if ne .Comment ""}}fmt.Println({{printf "%q" .Comment}}){{end}}
|
||||
var aliases []string
|
||||
{{- $name := .Name -}}
|
||||
{{range $alias, $func := $.Aliases}}
|
||||
{{if eq $name $func}}aliases = append(aliases, "{{$alias}}"){{end -}}
|
||||
{{- end}}
|
||||
if len(aliases) > 0 {
|
||||
fmt.Printf("Aliases: %s\n\n", strings.Join(aliases, ", "))
|
||||
}
|
||||
return
|
||||
{{end}}
|
||||
default:
|
||||
logger.Printf("Unknown target: %q\n", os.Args[1])
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
if len(os.Args) < 2 {
|
||||
{{- if .Default}}
|
||||
{{.DefaultFunc.TemplateString}}
|
||||
handleError(logger, err)
|
||||
return
|
||||
{{- else}}
|
||||
if err := list(); err != nil {
|
||||
logger.Println("Error:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
return
|
||||
{{- end}}
|
||||
}
|
||||
for _, target := range os.Args[1:] {
|
||||
switch strings.ToLower(target) {
|
||||
{{range $alias, $func := .Aliases}}
|
||||
case "{{lower $alias}}":
|
||||
target = "{{$func}}"
|
||||
{{- end}}
|
||||
}
|
||||
switch strings.ToLower(target) {
|
||||
{{range .Funcs }}
|
||||
case "{{lower .Name}}":
|
||||
if os.Getenv("MAGEFILE_VERBOSE") != "" {
|
||||
logger.Println("Running target:", "{{.Name}}")
|
||||
}
|
||||
{{.TemplateString}}
|
||||
handleError(logger, err)
|
||||
{{- end}}
|
||||
default:
|
||||
// should be impossible since we check this above.
|
||||
logger.Printf("Unknown target: %q\n", os.Args[1])
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
`
|
94
vendor/github.com/magefile/mage/magefile.go
generated
vendored
Normal file
94
vendor/github.com/magefile/mage/magefile.go
generated
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
//+build mage
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/magefile/mage/sh"
|
||||
)
|
||||
|
||||
// Runs "go install" for mage. This generates the version info the binary.
|
||||
func Install() error {
|
||||
ldf, err := flags()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
name := "mage"
|
||||
if runtime.GOOS == "windows" {
|
||||
name += ".exe"
|
||||
}
|
||||
gopath, err := sh.Output("go", "env", "GOPATH")
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't determine GOPATH: %v", err)
|
||||
}
|
||||
paths := strings.Split(gopath, string([]rune{os.PathListSeparator}))
|
||||
bin := filepath.Join(paths[0], "bin")
|
||||
// specifically don't mkdirall, if you have an invalid gopath in the first
|
||||
// place, that's not on us to fix.
|
||||
if err := os.Mkdir(bin, 0700); err != nil && !os.IsExist(err) {
|
||||
return fmt.Errorf("failed to create %q: %v", bin, err)
|
||||
}
|
||||
path := filepath.Join(bin, name)
|
||||
|
||||
// we use go build here because if someone built with go get, then `go
|
||||
// install` turns into a no-op, and `go install -a` fails on people's
|
||||
// machines that have go installed in a non-writeable directory (such as
|
||||
// normal OS installs in /usr/bin)
|
||||
return sh.RunV("go", "build", "-o", path, "-ldflags="+ldf, "github.com/magefile/mage")
|
||||
}
|
||||
|
||||
// Generates a new release. Expects the TAG environment variable to be set,
|
||||
// which will create a new tag with that name.
|
||||
func Release() (err error) {
|
||||
if os.Getenv("TAG") == "" {
|
||||
return errors.New("MSG and TAG environment variables are required")
|
||||
}
|
||||
if err := sh.RunV("git", "tag", "-a", "$TAG"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := sh.RunV("git", "push", "origin", "$TAG"); err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
sh.RunV("git", "tag", "--delete", "$TAG")
|
||||
sh.RunV("git", "push", "--delete", "origin", "$TAG")
|
||||
}
|
||||
}()
|
||||
return sh.RunV("goreleaser")
|
||||
}
|
||||
|
||||
// Remove the temporarily generated files from Release.
|
||||
func Clean() error {
|
||||
return sh.Rm("dist")
|
||||
}
|
||||
|
||||
func flags() (string, error) {
|
||||
timestamp := time.Now().Format(time.RFC3339)
|
||||
hash := hash()
|
||||
tag := tag()
|
||||
if tag == "" {
|
||||
tag = "dev"
|
||||
}
|
||||
return fmt.Sprintf(`-X "github.com/magefile/mage/mage.timestamp=%s" -X "github.com/magefile/mage/mage.commitHash=%s" -X "github.com/magefile/mage/mage.gitTag=%s"`, timestamp, hash, tag), nil
|
||||
}
|
||||
|
||||
// tag returns the git tag for the current branch or "" if none.
|
||||
func tag() string {
|
||||
s, _ := sh.Output("git", "describe", "--tags")
|
||||
return s
|
||||
}
|
||||
|
||||
// hash returns the git hash for the current repo or "" if none.
|
||||
func hash() string {
|
||||
hash, _ := sh.Output("git", "rev-parse", "--short", "HEAD")
|
||||
return hash
|
||||
}
|
11
vendor/github.com/magefile/mage/main.go
generated
vendored
Normal file
11
vendor/github.com/magefile/mage/main.go
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/magefile/mage/mage"
|
||||
)
|
||||
|
||||
func main() {
|
||||
os.Exit(mage.Main())
|
||||
}
|
166
vendor/github.com/magefile/mage/mg/deps.go
generated
vendored
Normal file
166
vendor/github.com/magefile/mage/mg/deps.go
generated
vendored
Normal file
@@ -0,0 +1,166 @@
|
||||
package mg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/magefile/mage/types"
|
||||
)
|
||||
|
||||
type onceMap struct {
|
||||
mu *sync.Mutex
|
||||
m map[string]*onceFun
|
||||
}
|
||||
|
||||
func (o *onceMap) LoadOrStore(s string, one *onceFun) *onceFun {
|
||||
defer o.mu.Unlock()
|
||||
o.mu.Lock()
|
||||
|
||||
existing, ok := o.m[s]
|
||||
if ok {
|
||||
return existing
|
||||
}
|
||||
o.m[s] = one
|
||||
return one
|
||||
}
|
||||
|
||||
var onces = &onceMap{
|
||||
mu: &sync.Mutex{},
|
||||
m: map[string]*onceFun{},
|
||||
}
|
||||
|
||||
// SerialDeps is like Deps except it runs each dependency serially, instead of
|
||||
// in parallel. This can be useful for resource intensive dependencies that
|
||||
// shouldn't be run at the same time.
|
||||
func SerialDeps(fns ...interface{}) {
|
||||
checkFns(fns)
|
||||
ctx := context.Background()
|
||||
for _, f := range fns {
|
||||
runDeps(ctx, f)
|
||||
}
|
||||
}
|
||||
|
||||
// SerialCtxDeps is like CtxDeps except it runs each dependency serially,
|
||||
// instead of in parallel. This can be useful for resource intensive
|
||||
// dependencies that shouldn't be run at the same time.
|
||||
func SerialCtxDeps(ctx context.Context, fns ...interface{}) {
|
||||
checkFns(fns)
|
||||
for _, f := range fns {
|
||||
runDeps(ctx, f)
|
||||
}
|
||||
}
|
||||
|
||||
// CtxDeps runs the given functions as dependencies of the calling function.
|
||||
// Dependencies must only be of type: github.com/magefile/mage/types.FuncType.
|
||||
// The function calling Deps is guaranteed that all dependent functions will be
|
||||
// run exactly once when Deps returns. Dependent functions may in turn declare
|
||||
// their own dependencies using Deps. Each dependency is run in their own
|
||||
// goroutines. Each function is given the context provided if the function
|
||||
// prototype allows for it.
|
||||
func CtxDeps(ctx context.Context, fns ...interface{}) {
|
||||
checkFns(fns)
|
||||
runDeps(ctx, fns...)
|
||||
}
|
||||
|
||||
// runDeps assumes you've already called checkFns.
|
||||
func runDeps(ctx context.Context, fns ...interface{}) {
|
||||
mu := &sync.Mutex{}
|
||||
var errs []string
|
||||
var exit int
|
||||
wg := &sync.WaitGroup{}
|
||||
for _, f := range fns {
|
||||
fn := addDep(ctx, f)
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer func() {
|
||||
if v := recover(); v != nil {
|
||||
mu.Lock()
|
||||
if err, ok := v.(error); ok {
|
||||
exit = changeExit(exit, ExitStatus(err))
|
||||
} else {
|
||||
exit = changeExit(exit, 1)
|
||||
}
|
||||
errs = append(errs, fmt.Sprint(v))
|
||||
mu.Unlock()
|
||||
}
|
||||
wg.Done()
|
||||
}()
|
||||
if err := fn.run(); err != nil {
|
||||
mu.Lock()
|
||||
errs = append(errs, fmt.Sprint(err))
|
||||
exit = changeExit(exit, ExitStatus(err))
|
||||
mu.Unlock()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
if len(errs) > 0 {
|
||||
panic(Fatal(exit, strings.Join(errs, "\n")))
|
||||
}
|
||||
}
|
||||
|
||||
func checkFns(fns []interface{}) {
|
||||
for _, f := range fns {
|
||||
if err := types.FuncCheck(f); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Deps runs the given functions with the default runtime context
|
||||
func Deps(fns ...interface{}) {
|
||||
CtxDeps(context.Background(), fns...)
|
||||
}
|
||||
|
||||
func changeExit(old, new int) int {
|
||||
if new == 0 {
|
||||
return old
|
||||
}
|
||||
if old == 0 {
|
||||
return new
|
||||
}
|
||||
if old == new {
|
||||
return old
|
||||
}
|
||||
// both different and both non-zero, just set
|
||||
// exit to 1. Nothing more we can do.
|
||||
return 1
|
||||
}
|
||||
|
||||
func addDep(ctx context.Context, f interface{}) *onceFun {
|
||||
var fn func(context.Context) error
|
||||
if fn = types.FuncTypeWrap(f); fn == nil {
|
||||
// should be impossible, since we already checked this
|
||||
panic("attempted to add a dep that did not match required type")
|
||||
}
|
||||
|
||||
n := name(f)
|
||||
of := onces.LoadOrStore(n, &onceFun{
|
||||
fn: fn,
|
||||
ctx: ctx,
|
||||
})
|
||||
return of
|
||||
}
|
||||
|
||||
func name(i interface{}) string {
|
||||
return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
|
||||
}
|
||||
|
||||
type onceFun struct {
|
||||
once sync.Once
|
||||
fn func(context.Context) error
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
func (o *onceFun) run() error {
|
||||
var err error
|
||||
o.once.Do(func() {
|
||||
err = o.fn(o.ctx)
|
||||
})
|
||||
return err
|
||||
}
|
51
vendor/github.com/magefile/mage/mg/errors.go
generated
vendored
Normal file
51
vendor/github.com/magefile/mage/mg/errors.go
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
package mg
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type fatalErr struct {
|
||||
code int
|
||||
error
|
||||
}
|
||||
|
||||
func (f fatalErr) ExitStatus() int {
|
||||
return f.code
|
||||
}
|
||||
|
||||
type exitStatus interface {
|
||||
ExitStatus() int
|
||||
}
|
||||
|
||||
// Fatal returns an error that will cause mage to print out the
|
||||
// given args and exit with the given exit code.
|
||||
func Fatal(code int, args ...interface{}) error {
|
||||
return fatalErr{
|
||||
code: code,
|
||||
error: errors.New(fmt.Sprint(args...)),
|
||||
}
|
||||
}
|
||||
|
||||
// Fatalf returns an error that will cause mage to print out the
|
||||
// given message and exit with an exit code of 1.
|
||||
func Fatalf(code int, format string, args ...interface{}) error {
|
||||
return fatalErr{
|
||||
code: code,
|
||||
error: fmt.Errorf(format, args...),
|
||||
}
|
||||
}
|
||||
|
||||
// ExitStatus queries the error for an exit status. If the error is nil, it
|
||||
// returns 0. If the error does not implement ExitStatus() int, it returns 1.
|
||||
// Otherwise it retiurns the value from ExitStatus().
|
||||
func ExitStatus(err error) int {
|
||||
if err == nil {
|
||||
return 0
|
||||
}
|
||||
exit, ok := err.(exitStatus)
|
||||
if !ok {
|
||||
return 1
|
||||
}
|
||||
return exit.ExitStatus()
|
||||
}
|
36
vendor/github.com/magefile/mage/mg/runtime.go
generated
vendored
Normal file
36
vendor/github.com/magefile/mage/mg/runtime.go
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
package mg
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// CacheEnv is the environment variable that users may set to change the
|
||||
// location where mage stores its compiled binaries.
|
||||
const CacheEnv = "MAGEFILE_CACHE"
|
||||
|
||||
// verboseEnv is the environment variable that indicates the user requested
|
||||
// verbose mode when running a magefile.
|
||||
const verboseEnv = "MAGEFILE_VERBOSE"
|
||||
|
||||
// Verbose reports whether a magefile was run with the verbose flag.
|
||||
func Verbose() bool {
|
||||
return os.Getenv(verboseEnv) != ""
|
||||
}
|
||||
|
||||
// CacheDir returns the directory where mage caches compiled binaries. It
|
||||
// defaults to $HOME/.magefile, but may be overridden by the MAGEFILE_CACHE
|
||||
// environment variable.
|
||||
func CacheDir() string {
|
||||
d := os.Getenv(CacheEnv)
|
||||
if d != "" {
|
||||
return d
|
||||
}
|
||||
switch runtime.GOOS {
|
||||
case "windows":
|
||||
return filepath.Join(os.Getenv("HOMEDRIVE"), os.Getenv("HOMEPATH"), "magefile")
|
||||
default:
|
||||
return filepath.Join(os.Getenv("HOME"), ".magefile")
|
||||
}
|
||||
}
|
13
vendor/github.com/magefile/mage/parse/import_go1.9.go
generated
vendored
Normal file
13
vendor/github.com/magefile/mage/parse/import_go1.9.go
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
// +build go1.9
|
||||
|
||||
package parse
|
||||
|
||||
import (
|
||||
"go/importer"
|
||||
"go/token"
|
||||
"go/types"
|
||||
)
|
||||
|
||||
func getImporter(*token.FileSet) types.Importer {
|
||||
return importer.For("source", nil)
|
||||
}
|
15
vendor/github.com/magefile/mage/parse/import_not_go1.9.go
generated
vendored
Normal file
15
vendor/github.com/magefile/mage/parse/import_not_go1.9.go
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
// +build !go1.9
|
||||
|
||||
package parse
|
||||
|
||||
import (
|
||||
"go/build"
|
||||
"go/token"
|
||||
"go/types"
|
||||
|
||||
"github.com/magefile/mage/parse/srcimporter"
|
||||
)
|
||||
|
||||
func getImporter(fset *token.FileSet) types.Importer {
|
||||
return srcimporter.New(&build.Default, fset, make(map[string]*types.Package))
|
||||
}
|
341
vendor/github.com/magefile/mage/parse/parse.go
generated
vendored
Normal file
341
vendor/github.com/magefile/mage/parse/parse.go
generated
vendored
Normal file
@@ -0,0 +1,341 @@
|
||||
package parse
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/build"
|
||||
"go/doc"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
mgTypes "github.com/magefile/mage/types"
|
||||
)
|
||||
|
||||
type PkgInfo struct {
|
||||
Funcs []Function
|
||||
DefaultIsError bool
|
||||
DefaultIsContext bool
|
||||
DefaultName string
|
||||
DefaultFunc Function
|
||||
Aliases map[string]string
|
||||
}
|
||||
|
||||
// Function represented a job function from a mage file
|
||||
type Function struct {
|
||||
Name string
|
||||
IsError bool
|
||||
IsContext bool
|
||||
Synopsis string
|
||||
Comment string
|
||||
}
|
||||
|
||||
// TemplateString returns code for the template switch to run the target.
|
||||
// It wraps each target call to match the func(context.Context) error that
|
||||
// runTarget requires.
|
||||
func (f Function) TemplateString() string {
|
||||
if f.IsContext && f.IsError {
|
||||
out := `wrapFn := func(ctx context.Context) error {
|
||||
return %s(ctx)
|
||||
}
|
||||
err := runTarget(wrapFn)`
|
||||
return fmt.Sprintf(out, f.Name)
|
||||
}
|
||||
if f.IsContext && !f.IsError {
|
||||
out := `wrapFn := func(ctx context.Context) error {
|
||||
%s(ctx)
|
||||
return nil
|
||||
}
|
||||
err := runTarget(wrapFn)`
|
||||
return fmt.Sprintf(out, f.Name)
|
||||
}
|
||||
if !f.IsContext && f.IsError {
|
||||
out := `wrapFn := func(ctx context.Context) error {
|
||||
return %s()
|
||||
}
|
||||
err := runTarget(wrapFn)`
|
||||
return fmt.Sprintf(out, f.Name)
|
||||
}
|
||||
if !f.IsContext && !f.IsError {
|
||||
out := `wrapFn := func(ctx context.Context) error {
|
||||
%s()
|
||||
return nil
|
||||
}
|
||||
err := runTarget(wrapFn)`
|
||||
return fmt.Sprintf(out, f.Name)
|
||||
}
|
||||
return `fmt.Printf("Error formatting job code\n")
|
||||
os.Exit(1)`
|
||||
}
|
||||
|
||||
// Package parses a package
|
||||
func Package(path string, files []string) (*PkgInfo, error) {
|
||||
fset := token.NewFileSet()
|
||||
|
||||
pkg, err := getPackage(path, files, fset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info, err := makeInfo(path, fset, pkg.Files)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pi := &PkgInfo{}
|
||||
|
||||
p := doc.New(pkg, "./", 0)
|
||||
for _, f := range p.Funcs {
|
||||
if f.Recv != "" {
|
||||
// skip methods
|
||||
continue
|
||||
}
|
||||
if !ast.IsExported(f.Name) {
|
||||
// skip non-exported functions
|
||||
continue
|
||||
}
|
||||
if typ := voidOrError(f.Decl.Type, info); typ != mgTypes.InvalidType {
|
||||
pi.Funcs = append(pi.Funcs, Function{
|
||||
Name: f.Name,
|
||||
Comment: f.Doc,
|
||||
Synopsis: sanitizeSynopsis(f),
|
||||
IsError: typ == mgTypes.ErrorType || typ == mgTypes.ContextErrorType,
|
||||
IsContext: typ == mgTypes.ContextVoidType || typ == mgTypes.ContextErrorType,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
setDefault(p, pi, info)
|
||||
setAliases(p, pi, info)
|
||||
|
||||
return pi, nil
|
||||
}
|
||||
|
||||
// sanitizeSynopsis sanitizes function Doc to create a summary.
|
||||
func sanitizeSynopsis(f *doc.Func) string {
|
||||
synopsis := doc.Synopsis(f.Doc)
|
||||
|
||||
// If the synopsis begins with the function name, remove it. This is done to
|
||||
// not repeat the text.
|
||||
// From:
|
||||
// clean Clean removes the temporarily generated files
|
||||
// To:
|
||||
// clean removes the temporarily generated files
|
||||
if syns := strings.Split(synopsis, " "); strings.EqualFold(f.Name, syns[0]) {
|
||||
return strings.Join(syns[1:], " ")
|
||||
}
|
||||
|
||||
return synopsis
|
||||
}
|
||||
|
||||
func setDefault(p *doc.Package, pi *PkgInfo, info types.Info) {
|
||||
for _, v := range p.Vars {
|
||||
for x, name := range v.Names {
|
||||
if name != "Default" {
|
||||
continue
|
||||
}
|
||||
spec := v.Decl.Specs[x].(*ast.ValueSpec)
|
||||
if len(spec.Values) != 1 {
|
||||
log.Println("warning: default declaration has multiple values")
|
||||
}
|
||||
id, ok := spec.Values[0].(*ast.Ident)
|
||||
if !ok {
|
||||
log.Println("warning: default declaration is not a function name")
|
||||
}
|
||||
for _, f := range pi.Funcs {
|
||||
if f.Name == id.Name {
|
||||
pi.DefaultName = f.Name
|
||||
pi.DefaultIsError = f.IsError
|
||||
pi.DefaultIsContext = f.IsContext
|
||||
pi.DefaultFunc = f
|
||||
return
|
||||
}
|
||||
}
|
||||
log.Println("warning: default declaration does not reference a mage target")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setAliases(p *doc.Package, pi *PkgInfo, info types.Info) {
|
||||
for _, v := range p.Vars {
|
||||
for x, name := range v.Names {
|
||||
if name != "Aliases" {
|
||||
continue
|
||||
}
|
||||
spec, ok := v.Decl.Specs[x].(*ast.ValueSpec)
|
||||
if !ok {
|
||||
log.Println("warning: aliases declaration is not a value")
|
||||
return
|
||||
}
|
||||
if len(spec.Values) != 1 {
|
||||
log.Println("warning: aliases declaration has multiple values")
|
||||
}
|
||||
comp, ok := spec.Values[0].(*ast.CompositeLit)
|
||||
if !ok {
|
||||
log.Println("warning: aliases declaration is not a map")
|
||||
return
|
||||
}
|
||||
pi.Aliases = make(map[string]string)
|
||||
for _, elem := range comp.Elts {
|
||||
kv, ok := elem.(*ast.KeyValueExpr)
|
||||
if !ok {
|
||||
log.Println("warning: alias declaration is not a map element")
|
||||
return
|
||||
}
|
||||
k, ok := kv.Key.(*ast.BasicLit)
|
||||
if !ok || k.Kind != token.STRING {
|
||||
log.Println("warning: alias is not a string")
|
||||
return
|
||||
}
|
||||
v, ok := kv.Value.(*ast.Ident)
|
||||
if !ok {
|
||||
log.Println("warning: alias target is not a function")
|
||||
return
|
||||
}
|
||||
alias := strings.Trim(k.Value, "\"")
|
||||
valid := false
|
||||
for _, f := range pi.Funcs {
|
||||
valid = valid || f.Name == v.Name
|
||||
}
|
||||
if !valid {
|
||||
log.Printf("warning: alias declaration (%s) does not reference a mage target", alias)
|
||||
}
|
||||
pi.Aliases[alias] = v.Name
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// getPackage returns the non-test package at the given path.
|
||||
func getPackage(path string, files []string, fset *token.FileSet) (*ast.Package, error) {
|
||||
fm := make(map[string]bool, len(files))
|
||||
for _, f := range files {
|
||||
fm[f] = true
|
||||
}
|
||||
|
||||
filter := func(f os.FileInfo) bool {
|
||||
return fm[f.Name()]
|
||||
}
|
||||
|
||||
pkgs, err := parser.ParseDir(fset, path, filter, parser.ParseComments)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse directory: %v", err)
|
||||
}
|
||||
|
||||
for name, pkg := range pkgs {
|
||||
if !strings.HasSuffix(name, "_test") {
|
||||
return pkg, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("no non-test packages found in %s", path)
|
||||
}
|
||||
|
||||
func makeInfo(dir string, fset *token.FileSet, files map[string]*ast.File) (types.Info, error) {
|
||||
goroot := os.Getenv("GOROOT")
|
||||
if goroot == "" {
|
||||
c := exec.Command("go", "env", "GOROOT")
|
||||
b, err := c.Output()
|
||||
if err != nil {
|
||||
return types.Info{}, fmt.Errorf("failed to get GOROOT from 'go env': %v", err)
|
||||
}
|
||||
goroot = strings.TrimSpace(string(b))
|
||||
if goroot == "" {
|
||||
return types.Info{}, fmt.Errorf("could not determine GOROOT")
|
||||
}
|
||||
}
|
||||
|
||||
build.Default.GOROOT = goroot
|
||||
|
||||
cfg := types.Config{
|
||||
Importer: getImporter(fset),
|
||||
}
|
||||
|
||||
info := types.Info{
|
||||
Types: make(map[ast.Expr]types.TypeAndValue),
|
||||
Defs: make(map[*ast.Ident]types.Object),
|
||||
Uses: make(map[*ast.Ident]types.Object),
|
||||
}
|
||||
|
||||
fs := make([]*ast.File, 0, len(files))
|
||||
for _, v := range files {
|
||||
fs = append(fs, v)
|
||||
}
|
||||
|
||||
_, err := cfg.Check(dir, fset, fs, &info)
|
||||
if err != nil {
|
||||
return info, fmt.Errorf("failed to check types in directory: %v", err)
|
||||
}
|
||||
return info, nil
|
||||
}
|
||||
|
||||
// errorOrVoid filters the list of functions to only those that return only an
|
||||
// error or have no return value, and have no parameters.
|
||||
func errorOrVoid(fns []*ast.FuncDecl, info types.Info) []*ast.FuncDecl {
|
||||
fds := []*ast.FuncDecl{}
|
||||
|
||||
for _, fn := range fns {
|
||||
if voidOrError(fn.Type, info) != mgTypes.InvalidType {
|
||||
fds = append(fds, fn)
|
||||
}
|
||||
}
|
||||
return fds
|
||||
}
|
||||
|
||||
func hasContextParam(ft *ast.FuncType, info types.Info) bool {
|
||||
if ft.Params.NumFields() == 1 {
|
||||
ret := ft.Params.List[0]
|
||||
t := info.TypeOf(ret.Type)
|
||||
if t != nil && t.String() == "context.Context" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func hasVoidReturn(ft *ast.FuncType, info types.Info) bool {
|
||||
res := ft.Results
|
||||
if res.NumFields() == 0 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func hasErrorReturn(ft *ast.FuncType, info types.Info) bool {
|
||||
res := ft.Results
|
||||
if res.NumFields() == 1 {
|
||||
ret := res.List[0]
|
||||
if len(ret.Names) > 1 {
|
||||
return false
|
||||
}
|
||||
t := info.TypeOf(ret.Type)
|
||||
if t != nil && t.String() == "error" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func voidOrError(ft *ast.FuncType, info types.Info) mgTypes.FuncType {
|
||||
if hasContextParam(ft, info) {
|
||||
if hasVoidReturn(ft, info) {
|
||||
return mgTypes.ContextVoidType
|
||||
}
|
||||
if hasErrorReturn(ft, info) {
|
||||
return mgTypes.ContextErrorType
|
||||
}
|
||||
}
|
||||
if ft.Params.NumFields() == 0 {
|
||||
if hasVoidReturn(ft, info) {
|
||||
return mgTypes.VoidType
|
||||
}
|
||||
if hasErrorReturn(ft, info) {
|
||||
return mgTypes.ErrorType
|
||||
}
|
||||
}
|
||||
return mgTypes.InvalidType
|
||||
}
|
40
vendor/github.com/magefile/mage/parse/srcimporter/sizes.go
generated
vendored
Normal file
40
vendor/github.com/magefile/mage/parse/srcimporter/sizes.go
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
// +build !go1.9
|
||||
|
||||
package srcimporter
|
||||
|
||||
import "go/types"
|
||||
|
||||
// common architecture word sizes and alignments
|
||||
var gcArchSizes = map[string]*types.StdSizes{
|
||||
"386": {4, 4},
|
||||
"arm": {4, 4},
|
||||
"arm64": {8, 8},
|
||||
"amd64": {8, 8},
|
||||
"amd64p32": {4, 8},
|
||||
"mips": {4, 4},
|
||||
"mipsle": {4, 4},
|
||||
"mips64": {8, 8},
|
||||
"mips64le": {8, 8},
|
||||
"ppc64": {8, 8},
|
||||
"ppc64le": {8, 8},
|
||||
"s390x": {8, 8},
|
||||
// When adding more architectures here,
|
||||
// update the doc string of SizesFor below.
|
||||
}
|
||||
|
||||
// SizesFor returns the Sizes used by a compiler for an architecture.
|
||||
// The result is nil if a compiler/architecture pair is not known.
|
||||
//
|
||||
// Supported architectures for compiler "gc":
|
||||
// "386", "arm", "arm64", "amd64", "amd64p32", "mips", "mipsle",
|
||||
// "mips64", "mips64le", "ppc64", "ppc64le", "s390x".
|
||||
func SizesFor(compiler, arch string) types.Sizes {
|
||||
if compiler != "gc" {
|
||||
return nil
|
||||
}
|
||||
s, ok := gcArchSizes[arch]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return s
|
||||
}
|
213
vendor/github.com/magefile/mage/parse/srcimporter/srcimporter.go
generated
vendored
Normal file
213
vendor/github.com/magefile/mage/parse/srcimporter/srcimporter.go
generated
vendored
Normal file
@@ -0,0 +1,213 @@
|
||||
// +build !go1.9
|
||||
|
||||
// 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 srcimporter implements importing directly
|
||||
// from source files rather than installed packages.
|
||||
package srcimporter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/build"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// An Importer provides the context for importing packages from source code.
|
||||
type Importer struct {
|
||||
ctxt *build.Context
|
||||
fset *token.FileSet
|
||||
sizes types.Sizes
|
||||
packages map[string]*types.Package
|
||||
}
|
||||
|
||||
// NewImporter returns a new Importer for the given context, file set, and map
|
||||
// of packages. The context is used to resolve import paths to package paths,
|
||||
// and identifying the files belonging to the package. If the context provides
|
||||
// non-nil file system functions, they are used instead of the regular package
|
||||
// os functions. The file set is used to track position information of package
|
||||
// files; and imported packages are added to the packages map.
|
||||
func New(ctxt *build.Context, fset *token.FileSet, packages map[string]*types.Package) *Importer {
|
||||
return &Importer{
|
||||
ctxt: ctxt,
|
||||
fset: fset,
|
||||
sizes: SizesFor(ctxt.Compiler, ctxt.GOARCH), // uses go/types default if GOARCH not found
|
||||
packages: packages,
|
||||
}
|
||||
}
|
||||
|
||||
// Importing is a sentinel taking the place in Importer.packages
|
||||
// for a package that is in the process of being imported.
|
||||
var importing types.Package
|
||||
|
||||
// Import(path) is a shortcut for ImportFrom(path, "", 0).
|
||||
func (p *Importer) Import(path string) (*types.Package, error) {
|
||||
return p.ImportFrom(path, "", 0)
|
||||
}
|
||||
|
||||
// ImportFrom imports the package with the given import path resolved from the given srcDir,
|
||||
// adds the new package to the set of packages maintained by the importer, and returns the
|
||||
// package. Package path resolution and file system operations are controlled by the context
|
||||
// maintained with the importer. The import mode must be zero but is otherwise ignored.
|
||||
// Packages that are not comprised entirely of pure Go files may fail to import because the
|
||||
// type checker may not be able to determine all exported entities (e.g. due to cgo dependencies).
|
||||
func (p *Importer) ImportFrom(path, srcDir string, mode types.ImportMode) (*types.Package, error) {
|
||||
if mode != 0 {
|
||||
panic("non-zero import mode")
|
||||
}
|
||||
|
||||
// determine package path (do vendor resolution)
|
||||
var bp *build.Package
|
||||
var err error
|
||||
switch {
|
||||
default:
|
||||
if abs, err := p.absPath(srcDir); err == nil { // see issue #14282
|
||||
srcDir = abs
|
||||
}
|
||||
bp, err = p.ctxt.Import(path, srcDir, build.FindOnly)
|
||||
|
||||
case build.IsLocalImport(path):
|
||||
// "./x" -> "srcDir/x"
|
||||
bp, err = p.ctxt.ImportDir(filepath.Join(srcDir, path), build.FindOnly)
|
||||
|
||||
case p.isAbsPath(path):
|
||||
return nil, fmt.Errorf("invalid absolute import path %q", path)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err // err may be *build.NoGoError - return as is
|
||||
}
|
||||
|
||||
// package unsafe is known to the type checker
|
||||
if bp.ImportPath == "unsafe" {
|
||||
return types.Unsafe, nil
|
||||
}
|
||||
|
||||
// no need to re-import if the package was imported completely before
|
||||
pkg := p.packages[bp.ImportPath]
|
||||
if pkg != nil {
|
||||
if pkg == &importing {
|
||||
return nil, fmt.Errorf("import cycle through package %q", bp.ImportPath)
|
||||
}
|
||||
if !pkg.Complete() {
|
||||
// Package exists but is not complete - we cannot handle this
|
||||
// at the moment since the source importer replaces the package
|
||||
// wholesale rather than augmenting it (see #19337 for details).
|
||||
// Return incomplete package with error (see #16088).
|
||||
return pkg, fmt.Errorf("reimported partially imported package %q", bp.ImportPath)
|
||||
}
|
||||
return pkg, nil
|
||||
}
|
||||
|
||||
p.packages[bp.ImportPath] = &importing
|
||||
defer func() {
|
||||
// clean up in case of error
|
||||
// TODO(gri) Eventually we may want to leave a (possibly empty)
|
||||
// package in the map in all cases (and use that package to
|
||||
// identify cycles). See also issue 16088.
|
||||
if p.packages[bp.ImportPath] == &importing {
|
||||
p.packages[bp.ImportPath] = nil
|
||||
}
|
||||
}()
|
||||
|
||||
// collect package files
|
||||
bp, err = p.ctxt.ImportDir(bp.Dir, 0)
|
||||
if err != nil {
|
||||
return nil, err // err may be *build.NoGoError - return as is
|
||||
}
|
||||
var filenames []string
|
||||
filenames = append(filenames, bp.GoFiles...)
|
||||
filenames = append(filenames, bp.CgoFiles...)
|
||||
|
||||
files, err := p.parseFiles(bp.Dir, filenames)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// type-check package files
|
||||
conf := types.Config{
|
||||
IgnoreFuncBodies: true,
|
||||
FakeImportC: true,
|
||||
Importer: p,
|
||||
Sizes: p.sizes,
|
||||
}
|
||||
pkg, err = conf.Check(bp.ImportPath, p.fset, files, nil)
|
||||
if err != nil {
|
||||
// Type-checking stops after the first error (types.Config.Error is not set),
|
||||
// so the returned package is very likely incomplete. Don't return it since
|
||||
// we don't know its condition: It's very likely unsafe to use and it's also
|
||||
// not added to p.packages which may cause further problems (issue #20837).
|
||||
return nil, fmt.Errorf("type-checking package %q failed (%v)", bp.ImportPath, err)
|
||||
}
|
||||
|
||||
p.packages[bp.ImportPath] = pkg
|
||||
return pkg, nil
|
||||
}
|
||||
|
||||
func (p *Importer) parseFiles(dir string, filenames []string) ([]*ast.File, error) {
|
||||
open := p.ctxt.OpenFile // possibly nil
|
||||
|
||||
files := make([]*ast.File, len(filenames))
|
||||
errors := make([]error, len(filenames))
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(len(filenames))
|
||||
for i, filename := range filenames {
|
||||
go func(i int, filepath string) {
|
||||
defer wg.Done()
|
||||
if open != nil {
|
||||
src, err := open(filepath)
|
||||
if err != nil {
|
||||
errors[i] = fmt.Errorf("opening package file %s failed (%v)", filepath, err)
|
||||
return
|
||||
}
|
||||
files[i], errors[i] = parser.ParseFile(p.fset, filepath, src, 0)
|
||||
src.Close() // ignore Close error - parsing may have succeeded which is all we need
|
||||
} else {
|
||||
// Special-case when ctxt doesn't provide a custom OpenFile and use the
|
||||
// parser's file reading mechanism directly. This appears to be quite a
|
||||
// bit faster than opening the file and providing an io.ReaderCloser in
|
||||
// both cases.
|
||||
// TODO(gri) investigate performance difference (issue #19281)
|
||||
files[i], errors[i] = parser.ParseFile(p.fset, filepath, nil, 0)
|
||||
}
|
||||
}(i, p.joinPath(dir, filename))
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
// if there are errors, return the first one for deterministic results
|
||||
for _, err := range errors {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return files, nil
|
||||
}
|
||||
|
||||
// context-controlled file system operations
|
||||
|
||||
func (p *Importer) absPath(path string) (string, error) {
|
||||
// TODO(gri) This should be using p.ctxt.AbsPath which doesn't
|
||||
// exist but probably should. See also issue #14282.
|
||||
return filepath.Abs(path)
|
||||
}
|
||||
|
||||
func (p *Importer) isAbsPath(path string) bool {
|
||||
if f := p.ctxt.IsAbsPath; f != nil {
|
||||
return f(path)
|
||||
}
|
||||
return filepath.IsAbs(path)
|
||||
}
|
||||
|
||||
func (p *Importer) joinPath(elem ...string) string {
|
||||
if f := p.ctxt.JoinPath; f != nil {
|
||||
return f(elem...)
|
||||
}
|
||||
return filepath.Join(elem...)
|
||||
}
|
165
vendor/github.com/magefile/mage/sh/cmd.go
generated
vendored
Normal file
165
vendor/github.com/magefile/mage/sh/cmd.go
generated
vendored
Normal file
@@ -0,0 +1,165 @@
|
||||
package sh
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/magefile/mage/mg"
|
||||
)
|
||||
|
||||
// RunCmd returns a function that will call Run with the given command. This is
|
||||
// useful for creating command aliases to make your scripts easier to read, like
|
||||
// this:
|
||||
//
|
||||
// // in a helper file somewhere
|
||||
// var g0 = sh.RunCmd("go") // go is a keyword :(
|
||||
//
|
||||
// // somewhere in your main code
|
||||
// if err := g0("install", "github.com/gohugo/hugo"); err != nil {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// Args passed to command get baked in as args to the command when you run it.
|
||||
// Any args passed in when you run the returned function will be appended to the
|
||||
// original args. For example, this is equivalent to the above:
|
||||
//
|
||||
// var goInstall = sh.RunCmd("go", "install") goInstall("github.com/gohugo/hugo")
|
||||
//
|
||||
// RunCmd uses Exec underneath, so see those docs for more details.
|
||||
func RunCmd(cmd string, args ...string) func(args ...string) error {
|
||||
return func(args2 ...string) error {
|
||||
return Run(cmd, append(args, args2...)...)
|
||||
}
|
||||
}
|
||||
|
||||
// OutCmd is like RunCmd except the command returns the output of the
|
||||
// command.
|
||||
func OutCmd(cmd string, args ...string) func(args ...string) (string, error) {
|
||||
return func(args2 ...string) (string, error) {
|
||||
return Output(cmd, append(args, args2...)...)
|
||||
}
|
||||
}
|
||||
|
||||
// Run is like RunWith, but doesn't specify any environment variables.
|
||||
func Run(cmd string, args ...string) error {
|
||||
return RunWith(nil, cmd, args...)
|
||||
}
|
||||
|
||||
// RunV is like Run, but always sends the command's stdout to os.Stdout.
|
||||
func RunV(cmd string, args ...string) error {
|
||||
_, err := Exec(nil, os.Stdout, os.Stderr, cmd, args...)
|
||||
return err
|
||||
}
|
||||
|
||||
// RunWith runs the given command, directing stderr to this program's stderr and
|
||||
// printing stdout to stdout if mage was run with -v. It adds adds env to the
|
||||
// environment variables for the command being run. Environment variables should
|
||||
// be in the format name=value.
|
||||
func RunWith(env map[string]string, cmd string, args ...string) error {
|
||||
var output io.Writer
|
||||
if mg.Verbose() {
|
||||
output = os.Stdout
|
||||
}
|
||||
_, err := Exec(env, output, os.Stderr, cmd, args...)
|
||||
return err
|
||||
}
|
||||
|
||||
// Output runs the command and returns the text from stdout.
|
||||
func Output(cmd string, args ...string) (string, error) {
|
||||
buf := &bytes.Buffer{}
|
||||
_, err := Exec(nil, buf, os.Stderr, cmd, args...)
|
||||
return strings.TrimSuffix(buf.String(), "\n"), err
|
||||
}
|
||||
|
||||
// OutputWith is like RunWith, ubt returns what is written to stdout.
|
||||
func OutputWith(env map[string]string, cmd string, args ...string) (string, error) {
|
||||
buf := &bytes.Buffer{}
|
||||
_, err := Exec(env, buf, os.Stderr, cmd, args...)
|
||||
return strings.TrimSuffix(buf.String(), "\n"), err
|
||||
}
|
||||
|
||||
// Exec executes the command, piping its stderr to mage's stderr and
|
||||
// piping its stdout to the given writer. If the command fails, it will return
|
||||
// an error that, if returned from a target or mg.Deps call, will cause mage to
|
||||
// exit with the same code as the command failed with. Env is a list of
|
||||
// environment variables to set when running the command, these override the
|
||||
// current environment variables set (which are also passed to the command). cmd
|
||||
// and args may include references to environment variables in $FOO format, in
|
||||
// which case these will be expanded before the command is run.
|
||||
//
|
||||
// Ran reports if the command ran (rather than was not found or not executable).
|
||||
// Code reports the exit code the command returned if it ran. If err == nil, ran
|
||||
// is always true and code is always 0.
|
||||
func Exec(env map[string]string, stdout, stderr io.Writer, cmd string, args ...string) (ran bool, err error) {
|
||||
expand := func(s string) string {
|
||||
s2, ok := env[s]
|
||||
if ok {
|
||||
return s2
|
||||
}
|
||||
return os.Getenv(s)
|
||||
}
|
||||
cmd = os.Expand(cmd, expand)
|
||||
for i := range args {
|
||||
args[i] = os.Expand(args[i], expand)
|
||||
}
|
||||
ran, code, err := run(env, stdout, stderr, cmd, args...)
|
||||
if err == nil {
|
||||
return true, nil
|
||||
}
|
||||
if ran {
|
||||
return ran, mg.Fatalf(code, `running "%s %s" failed with exit code %d`, cmd, strings.Join(args, " "), code)
|
||||
}
|
||||
return ran, fmt.Errorf(`failed to run "%s %s: %v"`, cmd, strings.Join(args, " "), err)
|
||||
}
|
||||
|
||||
func run(env map[string]string, stdout, stderr io.Writer, cmd string, args ...string) (ran bool, code int, err error) {
|
||||
c := exec.Command(cmd, args...)
|
||||
c.Env = os.Environ()
|
||||
for k, v := range env {
|
||||
c.Env = append(c.Env, k+"="+v)
|
||||
}
|
||||
c.Stderr = stderr
|
||||
c.Stdout = stdout
|
||||
c.Stdin = os.Stdin
|
||||
log.Println("exec:", cmd, strings.Join(args, " "))
|
||||
err = c.Run()
|
||||
return cmdRan(err), ExitStatus(err), err
|
||||
}
|
||||
|
||||
func cmdRan(err error) bool {
|
||||
if err == nil {
|
||||
return true
|
||||
}
|
||||
ee, ok := err.(*exec.ExitError)
|
||||
if ok {
|
||||
return ee.Exited()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type exitStatus interface {
|
||||
ExitStatus() int
|
||||
}
|
||||
|
||||
// ExitStatus returns the exit status of the error if it is an exec.ExitError
|
||||
// or if it implements ExitStatus() int.
|
||||
// 0 if it is nil or 1 if it is a different error.
|
||||
func ExitStatus(err error) int {
|
||||
if err == nil {
|
||||
return 0
|
||||
}
|
||||
if e, ok := err.(exitStatus); ok {
|
||||
return e.ExitStatus()
|
||||
}
|
||||
if e, ok := err.(*exec.ExitError); ok {
|
||||
if ex, ok := e.Sys().(exitStatus); ok {
|
||||
return ex.ExitStatus()
|
||||
}
|
||||
}
|
||||
return 1
|
||||
}
|
16
vendor/github.com/magefile/mage/sh/helpers.go
generated
vendored
Normal file
16
vendor/github.com/magefile/mage/sh/helpers.go
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
package sh
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
// Rm removes the given file or directory even if non-empty. It will not return
|
||||
// an error if the target doesn't exist, only if the target cannot be removed.
|
||||
func Rm(path string) error {
|
||||
err := os.RemoveAll(path)
|
||||
if err == nil || os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf(`failed to remove %s: %v`, path, err)
|
||||
}
|
122
vendor/github.com/magefile/mage/target/target.go
generated
vendored
Normal file
122
vendor/github.com/magefile/mage/target/target.go
generated
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
package target
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Path reports if any of the sources have been modified more recently
|
||||
// than the destination. Path does not descend into directories, it literally
|
||||
// just checks the modtime of each thing you pass to it.
|
||||
func Path(dst string, sources ...string) (bool, error) {
|
||||
stat, err := os.Stat(dst)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
srcTime := stat.ModTime()
|
||||
dt, err := loadTargets(sources)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
t := dt.modTime()
|
||||
if t.After(srcTime) {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Dir reports whether any of the sources have been modified
|
||||
// more recently than the destination. If a source or destination is
|
||||
// a directory, modtimes of files under those directories are compared
|
||||
// instead.
|
||||
func Dir(dst string, sources ...string) (bool, error) {
|
||||
stat, err := os.Stat(dst)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
srcTime := stat.ModTime()
|
||||
if stat.IsDir() {
|
||||
srcTime, err = calDirModTimeRecursive(stat)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
dt, err := loadTargets(sources)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
t, err := dt.modTimeDir()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if t.After(srcTime) {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func calDirModTimeRecursive(dir os.FileInfo) (time.Time, error) {
|
||||
t := dir.ModTime()
|
||||
ferr := filepath.Walk(dir.Name(), func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if info.ModTime().After(t) {
|
||||
t = info.ModTime()
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if ferr != nil {
|
||||
return time.Time{}, ferr
|
||||
}
|
||||
return t, nil
|
||||
}
|
||||
|
||||
type depTargets struct {
|
||||
src []os.FileInfo
|
||||
hasdir bool
|
||||
latest time.Time
|
||||
}
|
||||
|
||||
func loadTargets(targets []string) (*depTargets, error) {
|
||||
d := &depTargets{}
|
||||
for _, v := range targets {
|
||||
stat, err := os.Stat(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if stat.IsDir() {
|
||||
d.hasdir = true
|
||||
}
|
||||
d.src = append(d.src, stat)
|
||||
if stat.ModTime().After(d.latest) {
|
||||
d.latest = stat.ModTime()
|
||||
}
|
||||
}
|
||||
return d, nil
|
||||
}
|
||||
|
||||
func (d *depTargets) modTime() time.Time {
|
||||
return d.latest
|
||||
}
|
||||
|
||||
func (d *depTargets) modTimeDir() (time.Time, error) {
|
||||
if !d.hasdir {
|
||||
return d.latest, nil
|
||||
}
|
||||
var err error
|
||||
for _, i := range d.src {
|
||||
t := i.ModTime()
|
||||
if i.IsDir() {
|
||||
t, err = calDirModTimeRecursive(i)
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
}
|
||||
if t.After(d.latest) {
|
||||
d.latest = t
|
||||
}
|
||||
}
|
||||
return d.latest, nil
|
||||
}
|
58
vendor/github.com/magefile/mage/types/funcs.go
generated
vendored
Normal file
58
vendor/github.com/magefile/mage/types/funcs.go
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// FuncType indicates a prototype of build job function
|
||||
type FuncType int
|
||||
|
||||
// FuncTypes
|
||||
const (
|
||||
InvalidType FuncType = iota
|
||||
VoidType
|
||||
ErrorType
|
||||
ContextVoidType
|
||||
ContextErrorType
|
||||
)
|
||||
|
||||
// FuncCheck tests if a function is one of FuncType
|
||||
func FuncCheck(fn interface{}) error {
|
||||
switch fn.(type) {
|
||||
case func():
|
||||
return nil
|
||||
case func() error:
|
||||
return nil
|
||||
case func(context.Context):
|
||||
return nil
|
||||
case func(context.Context) error:
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("Invalid type for dependent function: %T. Dependencies must be func(), func() error, func(context.Context) or func(context.Context) error", fn)
|
||||
}
|
||||
|
||||
// FuncTypeWrap wraps a valid FuncType to FuncContextError
|
||||
func FuncTypeWrap(fn interface{}) func(context.Context) error {
|
||||
if FuncCheck(fn) == nil {
|
||||
switch f := fn.(type) {
|
||||
case func():
|
||||
return func(context.Context) error {
|
||||
f()
|
||||
return nil
|
||||
}
|
||||
case func() error:
|
||||
return func(context.Context) error {
|
||||
return f()
|
||||
}
|
||||
case func(context.Context):
|
||||
return func(ctx context.Context) error {
|
||||
f(ctx)
|
||||
return nil
|
||||
}
|
||||
case func(context.Context) error:
|
||||
return f
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
Reference in New Issue
Block a user