Add vendor deps
13
vendor/github.com/inconshreveable/mousetrap/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
Copyright 2014 Alan Shreve
|
||||
|
||||
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.
|
23
vendor/github.com/inconshreveable/mousetrap/README.md
generated
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
# mousetrap
|
||||
|
||||
mousetrap is a tiny library that answers a single question.
|
||||
|
||||
On a Windows machine, was the process invoked by someone double clicking on
|
||||
the executable file while browsing in explorer?
|
||||
|
||||
### Motivation
|
||||
|
||||
Windows developers unfamiliar with command line tools will often "double-click"
|
||||
the executable for a tool. Because most CLI tools print the help and then exit
|
||||
when invoked without arguments, this is often very frustrating for those users.
|
||||
|
||||
mousetrap provides a way to detect these invocations so that you can provide
|
||||
more helpful behavior and instructions on how to run the CLI tool. To see what
|
||||
this looks like, both from an organizational and a technical perspective, see
|
||||
https://inconshreveable.com/09-09-2014/sweat-the-small-stuff/
|
||||
|
||||
### The interface
|
||||
|
||||
The library exposes a single interface:
|
||||
|
||||
func StartedByExplorer() (bool)
|
15
vendor/github.com/inconshreveable/mousetrap/trap_others.go
generated
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
// +build !windows
|
||||
|
||||
package mousetrap
|
||||
|
||||
// StartedByExplorer returns true if the program was invoked by the user
|
||||
// double-clicking on the executable from explorer.exe
|
||||
//
|
||||
// It is conservative and returns false if any of the internal calls fail.
|
||||
// It does not guarantee that the program was run from a terminal. It only can tell you
|
||||
// whether it was launched from explorer.exe
|
||||
//
|
||||
// On non-Windows platforms, it always returns false.
|
||||
func StartedByExplorer() bool {
|
||||
return false
|
||||
}
|
98
vendor/github.com/inconshreveable/mousetrap/trap_windows.go
generated
vendored
Normal file
|
@ -0,0 +1,98 @@
|
|||
// +build windows
|
||||
// +build !go1.4
|
||||
|
||||
package mousetrap
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
// defined by the Win32 API
|
||||
th32cs_snapprocess uintptr = 0x2
|
||||
)
|
||||
|
||||
var (
|
||||
kernel = syscall.MustLoadDLL("kernel32.dll")
|
||||
CreateToolhelp32Snapshot = kernel.MustFindProc("CreateToolhelp32Snapshot")
|
||||
Process32First = kernel.MustFindProc("Process32FirstW")
|
||||
Process32Next = kernel.MustFindProc("Process32NextW")
|
||||
)
|
||||
|
||||
// ProcessEntry32 structure defined by the Win32 API
|
||||
type processEntry32 struct {
|
||||
dwSize uint32
|
||||
cntUsage uint32
|
||||
th32ProcessID uint32
|
||||
th32DefaultHeapID int
|
||||
th32ModuleID uint32
|
||||
cntThreads uint32
|
||||
th32ParentProcessID uint32
|
||||
pcPriClassBase int32
|
||||
dwFlags uint32
|
||||
szExeFile [syscall.MAX_PATH]uint16
|
||||
}
|
||||
|
||||
func getProcessEntry(pid int) (pe *processEntry32, err error) {
|
||||
snapshot, _, e1 := CreateToolhelp32Snapshot.Call(th32cs_snapprocess, uintptr(0))
|
||||
if snapshot == uintptr(syscall.InvalidHandle) {
|
||||
err = fmt.Errorf("CreateToolhelp32Snapshot: %v", e1)
|
||||
return
|
||||
}
|
||||
defer syscall.CloseHandle(syscall.Handle(snapshot))
|
||||
|
||||
var processEntry processEntry32
|
||||
processEntry.dwSize = uint32(unsafe.Sizeof(processEntry))
|
||||
ok, _, e1 := Process32First.Call(snapshot, uintptr(unsafe.Pointer(&processEntry)))
|
||||
if ok == 0 {
|
||||
err = fmt.Errorf("Process32First: %v", e1)
|
||||
return
|
||||
}
|
||||
|
||||
for {
|
||||
if processEntry.th32ProcessID == uint32(pid) {
|
||||
pe = &processEntry
|
||||
return
|
||||
}
|
||||
|
||||
ok, _, e1 = Process32Next.Call(snapshot, uintptr(unsafe.Pointer(&processEntry)))
|
||||
if ok == 0 {
|
||||
err = fmt.Errorf("Process32Next: %v", e1)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getppid() (pid int, err error) {
|
||||
pe, err := getProcessEntry(os.Getpid())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
pid = int(pe.th32ParentProcessID)
|
||||
return
|
||||
}
|
||||
|
||||
// StartedByExplorer returns true if the program was invoked by the user double-clicking
|
||||
// on the executable from explorer.exe
|
||||
//
|
||||
// It is conservative and returns false if any of the internal calls fail.
|
||||
// It does not guarantee that the program was run from a terminal. It only can tell you
|
||||
// whether it was launched from explorer.exe
|
||||
func StartedByExplorer() bool {
|
||||
ppid, err := getppid()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
pe, err := getProcessEntry(ppid)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
name := syscall.UTF16ToString(pe.szExeFile[:])
|
||||
return name == "explorer.exe"
|
||||
}
|
46
vendor/github.com/inconshreveable/mousetrap/trap_windows_1.4.go
generated
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
// +build windows
|
||||
// +build go1.4
|
||||
|
||||
package mousetrap
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func getProcessEntry(pid int) (*syscall.ProcessEntry32, error) {
|
||||
snapshot, err := syscall.CreateToolhelp32Snapshot(syscall.TH32CS_SNAPPROCESS, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer syscall.CloseHandle(snapshot)
|
||||
var procEntry syscall.ProcessEntry32
|
||||
procEntry.Size = uint32(unsafe.Sizeof(procEntry))
|
||||
if err = syscall.Process32First(snapshot, &procEntry); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for {
|
||||
if procEntry.ProcessID == uint32(pid) {
|
||||
return &procEntry, nil
|
||||
}
|
||||
err = syscall.Process32Next(snapshot, &procEntry)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// StartedByExplorer returns true if the program was invoked by the user double-clicking
|
||||
// on the executable from explorer.exe
|
||||
//
|
||||
// It is conservative and returns false if any of the internal calls fail.
|
||||
// It does not guarantee that the program was run from a terminal. It only can tell you
|
||||
// whether it was launched from explorer.exe
|
||||
func StartedByExplorer() bool {
|
||||
pe, err := getProcessEntry(os.Getppid())
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return "explorer.exe" == syscall.UTF16ToString(pe.ExeFile[:])
|
||||
}
|
2
vendor/github.com/magefile/mage/.gitattributes
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
site/* linguist-documentation
|
||||
vendor/* linguist-vendored
|
23
vendor/github.com/magefile/mage/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Test binary, build with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
|
||||
.glide/
|
||||
|
||||
# Magefile output
|
||||
mage_output_file.go
|
||||
|
||||
# VScode
|
||||
.vscode
|
||||
|
||||
# stupid osx
|
||||
.DS_Store
|
53
vendor/github.com/magefile/mage/.goreleaser.yml
generated
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
project_name: mage
|
||||
release:
|
||||
github:
|
||||
owner: magefile
|
||||
name: mage
|
||||
draft: true
|
||||
build:
|
||||
binary: mage
|
||||
main: .
|
||||
ldflags: -s -w -X github.com/magefile/mage/mage.timestamp={{.Date}} -X github.com/magefile/mage/mage.commitHash={{.Commit}} -X github.com/magefile/mage/mage.gitTag={{.Version}}
|
||||
goos:
|
||||
- darwin
|
||||
- linux
|
||||
- windows
|
||||
- freebsd
|
||||
- netbsd
|
||||
- openbsd
|
||||
- dragonfly
|
||||
goarch:
|
||||
- amd64
|
||||
- 386
|
||||
- arm
|
||||
- arm64
|
||||
ignore:
|
||||
- goos: openbsd
|
||||
goarch: arm
|
||||
goarm: 6
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
archive:
|
||||
name_template: "{{.Binary}}_{{.Version}}_{{.Os}}-{{.Arch}}"
|
||||
replacements:
|
||||
amd64: 64bit
|
||||
386: 32bit
|
||||
arm: ARM
|
||||
arm64: ARM64
|
||||
darwin: macOS
|
||||
linux: Linux
|
||||
windows: Windows
|
||||
openbsd: OpenBSD
|
||||
netbsd: NetBSD
|
||||
freebsd: FreeBSD
|
||||
dragonfly: DragonFlyBSD
|
||||
format: tar.gz
|
||||
format_overrides:
|
||||
- goos: windows
|
||||
format: zip
|
||||
files:
|
||||
- LICENSE
|
||||
snapshot:
|
||||
name_template: SNAPSHOT-{{ .Commit }}
|
||||
checksum:
|
||||
name_template: '{{ .ProjectName }}_{{ .Version }}_checksums.txt'
|
28
vendor/github.com/magefile/mage/.travis.yml
generated
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
language: go
|
||||
|
||||
# prevent double test runs for PRs
|
||||
branches:
|
||||
only:
|
||||
- "master"
|
||||
|
||||
# In theory, older versions would probably work fine, but since this isn't a
|
||||
# library, I'm not going to worry about older versions for now.
|
||||
go:
|
||||
- 1.9.x
|
||||
- 1.8.x
|
||||
- 1.7.x
|
||||
|
||||
# don't call go get ./... because this hides when deps are
|
||||
# not packaged into the vendor directory.
|
||||
install: true
|
||||
|
||||
# don't call go test -v because we want to be able to only show t.Log output when
|
||||
# a test fails
|
||||
script: go test -race $(go list ./... | grep -v /vendor/)
|
||||
|
||||
# run a test for every major OS
|
||||
env:
|
||||
- GOOS=linux
|
||||
- GOOS=windows
|
||||
- GOOS=darwin
|
||||
|
41
vendor/github.com/magefile/mage/CONTRIBUTING.md
generated
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
# 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(!). Let's try to 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 try to avoid using features of go and the stdlib that prevent mage from
|
||||
being buildable with old versions of Go. Definitely avoid anything that
|
||||
requires go 1.9.
|
||||
|
||||
## 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
|
@ -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
|
@ -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
|
@ -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.
|
35
vendor/github.com/magefile/mage/README.md
generated
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
<h1 align=center>mage</h1>
|
||||
<p align="center"><img src="https://user-images.githubusercontent.com/3185864/31061203-6f6743dc-a6ec-11e7-9469-b8d667d9bc3f.png"/></p>
|
||||
|
||||
<p align="center">Mage is a make/rake-like build tool using Go.</p>
|
||||
|
||||
[![Build Status](https://travis-ci.org/magefile/mage.svg?branch=master)](https://travis-ci.org/magefile/mage)
|
||||
|
||||
## Demo
|
||||
|
||||
[![Mage Demo](https://img.youtube.com/vi/GOqbD0lF-iA/maxresdefault.jpg)](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
|
1654
vendor/github.com/magefile/mage/build/build.go
generated
vendored
Normal file
446
vendor/github.com/magefile/mage/build/build_test.go
generated
vendored
Normal file
|
@ -0,0 +1,446 @@
|
|||
// 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
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMatch(t *testing.T) {
|
||||
ctxt := Default
|
||||
what := "default"
|
||||
match := func(tag string, want map[string]bool) {
|
||||
m := make(map[string]bool)
|
||||
if !ctxt.match(tag, m) {
|
||||
t.Errorf("%s context should match %s, does not", what, tag)
|
||||
}
|
||||
if !reflect.DeepEqual(m, want) {
|
||||
t.Errorf("%s tags = %v, want %v", tag, m, want)
|
||||
}
|
||||
}
|
||||
nomatch := func(tag string, want map[string]bool) {
|
||||
m := make(map[string]bool)
|
||||
if ctxt.match(tag, m) {
|
||||
t.Errorf("%s context should NOT match %s, does", what, tag)
|
||||
}
|
||||
if !reflect.DeepEqual(m, want) {
|
||||
t.Errorf("%s tags = %v, want %v", tag, m, want)
|
||||
}
|
||||
}
|
||||
|
||||
match(runtime.GOOS+","+runtime.GOARCH, map[string]bool{runtime.GOOS: true, runtime.GOARCH: true})
|
||||
match(runtime.GOOS+","+runtime.GOARCH+",!foo", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "foo": true})
|
||||
nomatch(runtime.GOOS+","+runtime.GOARCH+",foo", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "foo": true})
|
||||
|
||||
what = "modified"
|
||||
ctxt.BuildTags = []string{"foo"}
|
||||
match(runtime.GOOS+","+runtime.GOARCH, map[string]bool{runtime.GOOS: true, runtime.GOARCH: true})
|
||||
match(runtime.GOOS+","+runtime.GOARCH+",foo", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "foo": true})
|
||||
nomatch(runtime.GOOS+","+runtime.GOARCH+",!foo", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "foo": true})
|
||||
match(runtime.GOOS+","+runtime.GOARCH+",!bar", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "bar": true})
|
||||
nomatch(runtime.GOOS+","+runtime.GOARCH+",bar", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "bar": true})
|
||||
nomatch("!", map[string]bool{})
|
||||
}
|
||||
|
||||
func TestDotSlashImport(t *testing.T) {
|
||||
p, err := ImportDir("testdata/other", 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(p.Imports) != 1 || p.Imports[0] != "./file" {
|
||||
t.Fatalf("testdata/other: Imports=%v, want [./file]", p.Imports)
|
||||
}
|
||||
|
||||
p1, err := Import("./file", "testdata/other", 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if p1.Name != "file" {
|
||||
t.Fatalf("./file: Name=%q, want %q", p1.Name, "file")
|
||||
}
|
||||
dir := filepath.Clean("testdata/other/file") // Clean to use \ on Windows
|
||||
if p1.Dir != dir {
|
||||
t.Fatalf("./file: Dir=%q, want %q", p1.Name, dir)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEmptyImport(t *testing.T) {
|
||||
p, err := Import("", Default.GOROOT, FindOnly)
|
||||
if err == nil {
|
||||
t.Fatal(`Import("") returned nil error.`)
|
||||
}
|
||||
if p == nil {
|
||||
t.Fatal(`Import("") returned nil package.`)
|
||||
}
|
||||
if p.ImportPath != "" {
|
||||
t.Fatalf("ImportPath=%q, want %q.", p.ImportPath, "")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEmptyFolderImport(t *testing.T) {
|
||||
_, err := Import(".", "testdata/empty", 0)
|
||||
if _, ok := err.(*NoGoError); !ok {
|
||||
t.Fatal(`Import("testdata/empty") did not return NoGoError.`)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMultiplePackageImport(t *testing.T) {
|
||||
_, err := Import(".", "testdata/multi", 0)
|
||||
mpe, ok := err.(*MultiplePackageError)
|
||||
if !ok {
|
||||
t.Fatal(`Import("testdata/multi") did not return MultiplePackageError.`)
|
||||
}
|
||||
want := &MultiplePackageError{
|
||||
Dir: filepath.FromSlash("testdata/multi"),
|
||||
Packages: []string{"main", "test_package"},
|
||||
Files: []string{"file.go", "file_appengine.go"},
|
||||
}
|
||||
if !reflect.DeepEqual(mpe, want) {
|
||||
t.Errorf("got %#v; want %#v", mpe, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLocalDirectory(t *testing.T) {
|
||||
if runtime.GOOS == "darwin" {
|
||||
switch runtime.GOARCH {
|
||||
case "arm", "arm64":
|
||||
t.Skipf("skipping on %s/%s, no valid GOROOT", runtime.GOOS, runtime.GOARCH)
|
||||
}
|
||||
}
|
||||
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
p, err := ImportDir(cwd, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if p.ImportPath != "github.com/magefile/mage/build" {
|
||||
t.Fatalf("ImportPath=%q, want %q", p.ImportPath, "github.com/magefile/mage/build")
|
||||
}
|
||||
}
|
||||
|
||||
func TestShouldBuild(t *testing.T) {
|
||||
const file1 = "// +build tag1\n\n" +
|
||||
"package main\n"
|
||||
want1 := map[string]bool{"tag1": true}
|
||||
|
||||
const file2 = "// +build cgo\n\n" +
|
||||
"// This package implements parsing of tags like\n" +
|
||||
"// +build tag1\n" +
|
||||
"package build"
|
||||
want2 := map[string]bool{"cgo": true}
|
||||
|
||||
const file3 = "// Copyright The Go Authors.\n\n" +
|
||||
"package build\n\n" +
|
||||
"// shouldBuild checks tags given by lines of the form\n" +
|
||||
"// +build tag\n" +
|
||||
"func shouldBuild(content []byte)\n"
|
||||
want3 := map[string]bool{}
|
||||
|
||||
ctx := &Context{BuildTags: []string{"tag1"}}
|
||||
m := map[string]bool{}
|
||||
if !ctx.shouldBuild([]byte(file1), m, nil) {
|
||||
t.Errorf("shouldBuild(file1) = false, want true")
|
||||
}
|
||||
if !reflect.DeepEqual(m, want1) {
|
||||
t.Errorf("shouldBuild(file1) tags = %v, want %v", m, want1)
|
||||
}
|
||||
|
||||
m = map[string]bool{}
|
||||
if ctx.shouldBuild([]byte(file2), m, nil) {
|
||||
t.Errorf("shouldBuild(file2) = true, want false")
|
||||
}
|
||||
if !reflect.DeepEqual(m, want2) {
|
||||
t.Errorf("shouldBuild(file2) tags = %v, want %v", m, want2)
|
||||
}
|
||||
|
||||
m = map[string]bool{}
|
||||
ctx = &Context{BuildTags: nil}
|
||||
if !ctx.shouldBuild([]byte(file3), m, nil) {
|
||||
t.Errorf("shouldBuild(file3) = false, want true")
|
||||
}
|
||||
if !reflect.DeepEqual(m, want3) {
|
||||
t.Errorf("shouldBuild(file3) tags = %v, want %v", m, want3)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRequiredTags(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
file string
|
||||
should bool
|
||||
}{
|
||||
{
|
||||
"no req tag",
|
||||
"package main",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"has req tag",
|
||||
`// +build req
|
||||
|
||||
package main`,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"OR with req",
|
||||
`// +build no req
|
||||
|
||||
package main`,
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
ctx := &Context{
|
||||
BuildTags: []string{"req"},
|
||||
RequiredTags: []string{"req"},
|
||||
}
|
||||
for _, tst := range tests {
|
||||
t.Run(tst.name, func(t *testing.T) {
|
||||
if tst.should != ctx.shouldBuild([]byte(tst.file), nil, nil) {
|
||||
t.Errorf("shouldBuild = %v, want %v", !tst.should, tst.should)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type readNopCloser struct {
|
||||
io.Reader
|
||||
}
|
||||
|
||||
func (r readNopCloser) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
ctxtP9 = Context{GOARCH: "arm", GOOS: "plan9"}
|
||||
ctxtAndroid = Context{GOARCH: "arm", GOOS: "android"}
|
||||
)
|
||||
|
||||
var matchFileTests = []struct {
|
||||
ctxt Context
|
||||
name string
|
||||
data string
|
||||
match bool
|
||||
}{
|
||||
{ctxtP9, "foo_arm.go", "", true},
|
||||
{ctxtP9, "foo1_arm.go", "// +build linux\n\npackage main\n", false},
|
||||
{ctxtP9, "foo_darwin.go", "", false},
|
||||
{ctxtP9, "foo.go", "", true},
|
||||
{ctxtP9, "foo1.go", "// +build linux\n\npackage main\n", false},
|
||||
{ctxtP9, "foo.badsuffix", "", false},
|
||||
{ctxtAndroid, "foo_linux.go", "", true},
|
||||
{ctxtAndroid, "foo_android.go", "", true},
|
||||
{ctxtAndroid, "foo_plan9.go", "", false},
|
||||
{ctxtAndroid, "android.go", "", true},
|
||||
{ctxtAndroid, "plan9.go", "", true},
|
||||
{ctxtAndroid, "plan9_test.go", "", true},
|
||||
{ctxtAndroid, "arm.s", "", true},
|
||||
{ctxtAndroid, "amd64.s", "", true},
|
||||
}
|
||||
|
||||
func TestMatchFile(t *testing.T) {
|
||||
for _, tt := range matchFileTests {
|
||||
ctxt := tt.ctxt
|
||||
ctxt.OpenFile = func(path string) (r io.ReadCloser, err error) {
|
||||
if path != "x+"+tt.name {
|
||||
t.Fatalf("OpenFile asked for %q, expected %q", path, "x+"+tt.name)
|
||||
}
|
||||
return &readNopCloser{strings.NewReader(tt.data)}, nil
|
||||
}
|
||||
ctxt.JoinPath = func(elem ...string) string {
|
||||
return strings.Join(elem, "+")
|
||||
}
|
||||
match, err := ctxt.MatchFile("x", tt.name)
|
||||
if match != tt.match || err != nil {
|
||||
t.Fatalf("MatchFile(%q) = %v, %v, want %v, nil", tt.name, match, err, tt.match)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestImportCmd(t *testing.T) {
|
||||
if runtime.GOOS == "darwin" {
|
||||
switch runtime.GOARCH {
|
||||
case "arm", "arm64":
|
||||
t.Skipf("skipping on %s/%s, no valid GOROOT", runtime.GOOS, runtime.GOARCH)
|
||||
}
|
||||
}
|
||||
|
||||
p, err := Import("cmd/internal/objfile", "", 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !strings.HasSuffix(filepath.ToSlash(p.Dir), "src/cmd/internal/objfile") {
|
||||
t.Fatalf("Import cmd/internal/objfile returned Dir=%q, want %q", filepath.ToSlash(p.Dir), ".../src/cmd/internal/objfile")
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
expandSrcDirPath = filepath.Join(string(filepath.Separator)+"projects", "src", "add")
|
||||
)
|
||||
|
||||
var expandSrcDirTests = []struct {
|
||||
input, expected string
|
||||
}{
|
||||
{"-L ${SRCDIR}/libs -ladd", "-L /projects/src/add/libs -ladd"},
|
||||
{"${SRCDIR}/add_linux_386.a -pthread -lstdc++", "/projects/src/add/add_linux_386.a -pthread -lstdc++"},
|
||||
{"Nothing to expand here!", "Nothing to expand here!"},
|
||||
{"$", "$"},
|
||||
{"$$", "$$"},
|
||||
{"${", "${"},
|
||||
{"$}", "$}"},
|
||||
{"$FOO ${BAR}", "$FOO ${BAR}"},
|
||||
{"Find me the $SRCDIRECTORY.", "Find me the $SRCDIRECTORY."},
|
||||
{"$SRCDIR is missing braces", "$SRCDIR is missing braces"},
|
||||
}
|
||||
|
||||
func TestExpandSrcDir(t *testing.T) {
|
||||
for _, test := range expandSrcDirTests {
|
||||
output, _ := expandSrcDir(test.input, expandSrcDirPath)
|
||||
if output != test.expected {
|
||||
t.Errorf("%q expands to %q with SRCDIR=%q when %q is expected", test.input, output, expandSrcDirPath, test.expected)
|
||||
} else {
|
||||
t.Logf("%q expands to %q with SRCDIR=%q", test.input, output, expandSrcDirPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestShellSafety(t *testing.T) {
|
||||
tests := []struct {
|
||||
input, srcdir, expected string
|
||||
result bool
|
||||
}{
|
||||
{"-I${SRCDIR}/../include", "/projects/src/issue 11868", "-I/projects/src/issue 11868/../include", true},
|
||||
{"-I${SRCDIR}", "wtf$@%", "-Iwtf$@%", true},
|
||||
{"-X${SRCDIR}/1,${SRCDIR}/2", "/projects/src/issue 11868", "-X/projects/src/issue 11868/1,/projects/src/issue 11868/2", true},
|
||||
{"-I/tmp -I/tmp", "/tmp2", "-I/tmp -I/tmp", true},
|
||||
{"-I/tmp", "/tmp/[0]", "-I/tmp", true},
|
||||
{"-I${SRCDIR}/dir", "/tmp/[0]", "-I/tmp/[0]/dir", false},
|
||||
{"-I${SRCDIR}/dir", "/tmp/go go", "-I/tmp/go go/dir", true},
|
||||
{"-I${SRCDIR}/dir dir", "/tmp/go", "-I/tmp/go/dir dir", true},
|
||||
}
|
||||
for _, test := range tests {
|
||||
output, ok := expandSrcDir(test.input, test.srcdir)
|
||||
if ok != test.result {
|
||||
t.Errorf("Expected %t while %q expands to %q with SRCDIR=%q; got %t", test.result, test.input, output, test.srcdir, ok)
|
||||
}
|
||||
if output != test.expected {
|
||||
t.Errorf("Expected %q while %q expands with SRCDIR=%q; got %q", test.expected, test.input, test.srcdir, output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Want to get a "cannot find package" error when directory for package does not exist.
|
||||
// There should be valid partial information in the returned non-nil *Package.
|
||||
func TestImportDirNotExist(t *testing.T) {
|
||||
MustHaveGoBuild(t) // really must just have source
|
||||
ctxt := Default
|
||||
ctxt.GOPATH = ""
|
||||
|
||||
tests := []struct {
|
||||
label string
|
||||
path, srcDir string
|
||||
mode ImportMode
|
||||
}{
|
||||
{"Import(full, 0)", "go/build/doesnotexist", "", 0},
|
||||
{"Import(local, 0)", "./doesnotexist", filepath.Join(ctxt.GOROOT, "src/go/build"), 0},
|
||||
{"Import(full, FindOnly)", "go/build/doesnotexist", "", FindOnly},
|
||||
{"Import(local, FindOnly)", "./doesnotexist", filepath.Join(ctxt.GOROOT, "src/go/build"), FindOnly},
|
||||
}
|
||||
for _, test := range tests {
|
||||
p, err := ctxt.Import(test.path, test.srcDir, test.mode)
|
||||
if err == nil || !strings.HasPrefix(err.Error(), "cannot find package") {
|
||||
t.Errorf(`%s got error: %q, want "cannot find package" error`, test.label, err)
|
||||
}
|
||||
// If an error occurs, build.Import is documented to return
|
||||
// a non-nil *Package containing partial information.
|
||||
if p == nil {
|
||||
t.Fatalf(`%s got nil p, want non-nil *Package`, test.label)
|
||||
}
|
||||
// Verify partial information in p.
|
||||
if p.ImportPath != "go/build/doesnotexist" {
|
||||
t.Errorf(`%s got p.ImportPath: %q, want "go/build/doesnotexist"`, test.label, p.ImportPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestImportVendor(t *testing.T) {
|
||||
MustHaveGoBuild(t) // really must just have source
|
||||
ctxt := Default
|
||||
ctxt.GOPATH = ""
|
||||
p, err := ctxt.Import("golang_org/x/net/http2/hpack", filepath.Join(ctxt.GOROOT, "src/net/http"), 0)
|
||||
if err != nil {
|
||||
t.Fatalf("cannot find vendored golang_org/x/net/http2/hpack from net/http directory: %v", err)
|
||||
}
|
||||
want := "vendor/golang_org/x/net/http2/hpack"
|
||||
if p.ImportPath != want {
|
||||
t.Fatalf("Import succeeded but found %q, want %q", p.ImportPath, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestImportVendorFailure(t *testing.T) {
|
||||
MustHaveGoBuild(t) // really must just have source
|
||||
ctxt := Default
|
||||
ctxt.GOPATH = ""
|
||||
p, err := ctxt.Import("x.com/y/z", filepath.Join(ctxt.GOROOT, "src/net/http"), 0)
|
||||
if err == nil {
|
||||
t.Fatalf("found made-up package x.com/y/z in %s", p.Dir)
|
||||
}
|
||||
|
||||
e := err.Error()
|
||||
if !strings.Contains(e, " (vendor tree)") {
|
||||
t.Fatalf("error on failed import does not mention GOROOT/src/vendor directory:\n%s", e)
|
||||
}
|
||||
}
|
||||
|
||||
func TestImportVendorParentFailure(t *testing.T) {
|
||||
MustHaveGoBuild(t) // really must just have source
|
||||
ctxt := Default
|
||||
ctxt.GOPATH = ""
|
||||
// This import should fail because the vendor/golang.org/x/net/http2 directory has no source code.
|
||||
p, err := ctxt.Import("golang_org/x/net/http2", filepath.Join(ctxt.GOROOT, "src/net/http"), 0)
|
||||
if err == nil {
|
||||
t.Fatalf("found empty parent in %s", p.Dir)
|
||||
}
|
||||
if p != nil && p.Dir != "" {
|
||||
t.Fatalf("decided to use %s", p.Dir)
|
||||
}
|
||||
e := err.Error()
|
||||
if !strings.Contains(e, " (vendor tree)") {
|
||||
t.Fatalf("error on failed import does not mention GOROOT/src/vendor directory:\n%s", e)
|
||||
}
|
||||
}
|
||||
|
||||
// HasGoBuild reports whether the current system can build programs with ``go build''
|
||||
// and then run them with os.StartProcess or exec.Command.
|
||||
func HasGoBuild() bool {
|
||||
switch runtime.GOOS {
|
||||
case "android", "nacl":
|
||||
return false
|
||||
case "darwin":
|
||||
if strings.HasPrefix(runtime.GOARCH, "arm") {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// MustHaveGoBuild checks that the current system can build programs with ``go build''
|
||||
// and then run them with os.StartProcess or exec.Command.
|
||||
// If not, MustHaveGoBuild calls t.Skip with an explanation.
|
||||
func MustHaveGoBuild(t *testing.T) {
|
||||
if !HasGoBuild() {
|
||||
t.Skipf("skipping test: 'go build' not available on %s/%s", runtime.GOOS, runtime.GOARCH)
|
||||
}
|
||||
}
|
556
vendor/github.com/magefile/mage/build/deps_test.go
generated
vendored
Normal file
|
@ -0,0 +1,556 @@
|
|||
// 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.
|
||||
|
||||
// This file exercises the import parser but also checks that
|
||||
// some low-level packages do not have new dependencies added.
|
||||
|
||||
package build
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// pkgDeps defines the expected dependencies between packages in
|
||||
// the Go source tree. It is a statement of policy.
|
||||
// Changes should not be made to this map without prior discussion.
|
||||
//
|
||||
// The map contains two kinds of entries:
|
||||
// 1) Lower-case keys are standard import paths and list the
|
||||
// allowed imports in that package.
|
||||
// 2) Upper-case keys define aliases for package sets, which can then
|
||||
// be used as dependencies by other rules.
|
||||
//
|
||||
// DO NOT CHANGE THIS DATA TO FIX BUILDS.
|
||||
//
|
||||
var pkgDeps = map[string][]string{
|
||||
// L0 is the lowest level, core, nearly unavoidable packages.
|
||||
"errors": {},
|
||||
"io": {"errors", "sync"},
|
||||
"runtime": {"unsafe", "runtime/internal/atomic", "runtime/internal/sys"},
|
||||
"runtime/internal/sys": {},
|
||||
"runtime/internal/atomic": {"unsafe", "runtime/internal/sys"},
|
||||
"internal/race": {"runtime", "unsafe"},
|
||||
"sync": {"internal/race", "runtime", "sync/atomic", "unsafe"},
|
||||
"sync/atomic": {"unsafe"},
|
||||
"unsafe": {},
|
||||
"internal/cpu": {"runtime"},
|
||||
|
||||
"L0": {
|
||||
"errors",
|
||||
"io",
|
||||
"runtime",
|
||||
"runtime/internal/atomic",
|
||||
"sync",
|
||||
"sync/atomic",
|
||||
"unsafe",
|
||||
"internal/cpu",
|
||||
},
|
||||
|
||||
// L1 adds simple functions and strings processing,
|
||||
// but not Unicode tables.
|
||||
"math": {"internal/cpu", "unsafe"},
|
||||
"math/bits": {},
|
||||
"math/cmplx": {"math"},
|
||||
"math/rand": {"L0", "math"},
|
||||
"strconv": {"L0", "unicode/utf8", "math"},
|
||||
"unicode/utf16": {},
|
||||
"unicode/utf8": {},
|
||||
|
||||
"L1": {
|
||||
"L0",
|
||||
"math",
|
||||
"math/bits",
|
||||
"math/cmplx",
|
||||
"math/rand",
|
||||
"sort",
|
||||
"strconv",
|
||||
"unicode/utf16",
|
||||
"unicode/utf8",
|
||||
},
|
||||
|
||||
// L2 adds Unicode and strings processing.
|
||||
"bufio": {"L0", "unicode/utf8", "bytes"},
|
||||
"bytes": {"L0", "unicode", "unicode/utf8"},
|
||||
"path": {"L0", "unicode/utf8", "strings"},
|
||||
"strings": {"L0", "unicode", "unicode/utf8"},
|
||||
"unicode": {},
|
||||
|
||||
"L2": {
|
||||
"L1",
|
||||
"bufio",
|
||||
"bytes",
|
||||
"path",
|
||||
"strings",
|
||||
"unicode",
|
||||
},
|
||||
|
||||
// L3 adds reflection and some basic utility packages
|
||||
// and interface definitions, but nothing that makes
|
||||
// system calls.
|
||||
"crypto": {"L2", "hash"}, // interfaces
|
||||
"crypto/cipher": {"L2", "crypto/subtle"},
|
||||
"crypto/subtle": {},
|
||||
"encoding/base32": {"L2"},
|
||||
"encoding/base64": {"L2"},
|
||||
"encoding/binary": {"L2", "reflect"},
|
||||
"hash": {"L2"}, // interfaces
|
||||
"hash/adler32": {"L2", "hash"},
|
||||
"hash/crc32": {"L2", "hash"},
|
||||
"hash/crc64": {"L2", "hash"},
|
||||
"hash/fnv": {"L2", "hash"},
|
||||
"image": {"L2", "image/color"}, // interfaces
|
||||
"image/color": {"L2"}, // interfaces
|
||||
"image/color/palette": {"L2", "image/color"},
|
||||
"reflect": {"L2"},
|
||||
"sort": {"reflect"},
|
||||
|
||||
"L3": {
|
||||
"L2",
|
||||
"crypto",
|
||||
"crypto/cipher",
|
||||
"crypto/internal/cipherhw",
|
||||
"crypto/subtle",
|
||||
"encoding/base32",
|
||||
"encoding/base64",
|
||||
"encoding/binary",
|
||||
"hash",
|
||||
"hash/adler32",
|
||||
"hash/crc32",
|
||||
"hash/crc64",
|
||||
"hash/fnv",
|
||||
"image",
|
||||
"image/color",
|
||||
"image/color/palette",
|
||||
"reflect",
|
||||
},
|
||||
|
||||
// End of linear dependency definitions.
|
||||
|
||||
// Operating system access.
|
||||
"syscall": {"L0", "internal/race", "internal/syscall/windows/sysdll", "unicode/utf16"},
|
||||
"internal/syscall/unix": {"L0", "syscall"},
|
||||
"internal/syscall/windows": {"L0", "syscall", "internal/syscall/windows/sysdll"},
|
||||
"internal/syscall/windows/registry": {"L0", "syscall", "internal/syscall/windows/sysdll", "unicode/utf16"},
|
||||
"time": {
|
||||
// "L0" without the "io" package:
|
||||
"errors",
|
||||
"runtime",
|
||||
"runtime/internal/atomic",
|
||||
"sync",
|
||||
"sync/atomic",
|
||||
"unsafe",
|
||||
// Other time dependencies:
|
||||
"internal/syscall/windows/registry",
|
||||
"syscall",
|
||||
},
|
||||
|
||||
"internal/poll": {"L0", "internal/race", "syscall", "time", "unicode/utf16", "unicode/utf8"},
|
||||
"os": {"L1", "os", "syscall", "time", "internal/poll", "internal/syscall/windows"},
|
||||
"path/filepath": {"L2", "os", "syscall"},
|
||||
"io/ioutil": {"L2", "os", "path/filepath", "time"},
|
||||
"os/exec": {"L2", "os", "context", "path/filepath", "syscall"},
|
||||
"os/signal": {"L2", "os", "syscall"},
|
||||
|
||||
// OS enables basic operating system functionality,
|
||||
// but not direct use of package syscall, nor os/signal.
|
||||
"OS": {
|
||||
"io/ioutil",
|
||||
"os",
|
||||
"os/exec",
|
||||
"path/filepath",
|
||||
"time",
|
||||
},
|
||||
|
||||
// Formatted I/O: few dependencies (L1) but we must add reflect.
|
||||
"fmt": {"L1", "os", "reflect"},
|
||||
"log": {"L1", "os", "fmt", "time"},
|
||||
|
||||
// Packages used by testing must be low-level (L2+fmt).
|
||||
"regexp": {"L2", "regexp/syntax"},
|
||||
"regexp/syntax": {"L2"},
|
||||
"runtime/debug": {"L2", "fmt", "io/ioutil", "os", "time"},
|
||||
"runtime/pprof": {"L2", "compress/gzip", "context", "encoding/binary", "fmt", "io/ioutil", "os", "text/tabwriter", "time"},
|
||||
"runtime/trace": {"L0"},
|
||||
"text/tabwriter": {"L2"},
|
||||
|
||||
"testing": {"L2", "flag", "fmt", "internal/race", "os", "runtime/debug", "runtime/pprof", "runtime/trace", "time"},
|
||||
"testing/iotest": {"L2", "log"},
|
||||
"testing/quick": {"L2", "flag", "fmt", "reflect", "time"},
|
||||
"internal/testenv": {"L2", "OS", "flag", "testing", "syscall"},
|
||||
|
||||
// L4 is defined as L3+fmt+log+time, because in general once
|
||||
// you're using L3 packages, use of fmt, log, or time is not a big deal.
|
||||
"L4": {
|
||||
"L3",
|
||||
"fmt",
|
||||
"log",
|
||||
"time",
|
||||
},
|
||||
|
||||
// Go parser.
|
||||
"go/ast": {"L4", "OS", "go/scanner", "go/token"},
|
||||
"go/doc": {"L4", "go/ast", "go/token", "regexp", "text/template"},
|
||||
"go/parser": {"L4", "OS", "go/ast", "go/scanner", "go/token"},
|
||||
"go/printer": {"L4", "OS", "go/ast", "go/scanner", "go/token", "text/tabwriter"},
|
||||
"go/scanner": {"L4", "OS", "go/token"},
|
||||
"go/token": {"L4"},
|
||||
|
||||
"GOPARSER": {
|
||||
"go/ast",
|
||||
"go/doc",
|
||||
"go/parser",
|
||||
"go/printer",
|
||||
"go/scanner",
|
||||
"go/token",
|
||||
},
|
||||
|
||||
"go/format": {"L4", "GOPARSER", "internal/format"},
|
||||
"internal/format": {"L4", "GOPARSER"},
|
||||
|
||||
// Go type checking.
|
||||
"go/constant": {"L4", "go/token", "math/big"},
|
||||
"go/importer": {"L4", "go/build", "go/internal/gccgoimporter", "go/internal/gcimporter", "go/internal/srcimporter", "go/token", "go/types"},
|
||||
"go/internal/gcimporter": {"L4", "OS", "go/build", "go/constant", "go/token", "go/types", "text/scanner"},
|
||||
"go/internal/gccgoimporter": {"L4", "OS", "debug/elf", "go/constant", "go/token", "go/types", "text/scanner"},
|
||||
"go/internal/srcimporter": {"L4", "fmt", "go/ast", "go/build", "go/parser", "go/token", "go/types", "path/filepath"},
|
||||
"go/types": {"L4", "GOPARSER", "container/heap", "go/constant"},
|
||||
|
||||
// One of a kind.
|
||||
"archive/tar": {"L4", "OS", "syscall"},
|
||||
"archive/zip": {"L4", "OS", "compress/flate"},
|
||||
"container/heap": {"sort"},
|
||||
"compress/bzip2": {"L4"},
|
||||
"compress/flate": {"L4"},
|
||||
"compress/gzip": {"L4", "compress/flate"},
|
||||
"compress/lzw": {"L4"},
|
||||
"compress/zlib": {"L4", "compress/flate"},
|
||||
"context": {"errors", "fmt", "reflect", "sync", "time"},
|
||||
"database/sql": {"L4", "container/list", "context", "database/sql/driver", "database/sql/internal"},
|
||||
"database/sql/driver": {"L4", "context", "time", "database/sql/internal"},
|
||||
"debug/dwarf": {"L4"},
|
||||
"debug/elf": {"L4", "OS", "debug/dwarf", "compress/zlib"},
|
||||
"debug/gosym": {"L4"},
|
||||
"debug/macho": {"L4", "OS", "debug/dwarf"},
|
||||
"debug/pe": {"L4", "OS", "debug/dwarf"},
|
||||
"debug/plan9obj": {"L4", "OS"},
|
||||
"encoding": {"L4"},
|
||||
"encoding/ascii85": {"L4"},
|
||||
"encoding/asn1": {"L4", "math/big"},
|
||||
"encoding/csv": {"L4"},
|
||||
"encoding/gob": {"L4", "OS", "encoding"},
|
||||
"encoding/hex": {"L4"},
|
||||
"encoding/json": {"L4", "encoding"},
|
||||
"encoding/pem": {"L4"},
|
||||
"encoding/xml": {"L4", "encoding"},
|
||||
"flag": {"L4", "OS"},
|
||||
"go/build": {"L4", "OS", "GOPARSER"},
|
||||
"html": {"L4"},
|
||||
"image/draw": {"L4", "image/internal/imageutil"},
|
||||
"image/gif": {"L4", "compress/lzw", "image/color/palette", "image/draw"},
|
||||
"image/internal/imageutil": {"L4"},
|
||||
"image/jpeg": {"L4", "image/internal/imageutil"},
|
||||
"image/png": {"L4", "compress/zlib"},
|
||||
"index/suffixarray": {"L4", "regexp"},
|
||||
"internal/singleflight": {"sync"},
|
||||
"internal/trace": {"L4", "OS"},
|
||||
"math/big": {"L4"},
|
||||
"mime": {"L4", "OS", "syscall", "internal/syscall/windows/registry"},
|
||||
"mime/quotedprintable": {"L4"},
|
||||
"net/internal/socktest": {"L4", "OS", "syscall"},
|
||||
"net/url": {"L4"},
|
||||
"plugin": {"L0", "OS", "CGO"},
|
||||
"runtime/pprof/internal/profile": {"L4", "OS", "compress/gzip", "regexp"},
|
||||
"testing/internal/testdeps": {"L4", "runtime/pprof", "regexp"},
|
||||
"text/scanner": {"L4", "OS"},
|
||||
"text/template/parse": {"L4"},
|
||||
|
||||
"html/template": {
|
||||
"L4", "OS", "encoding/json", "html", "text/template",
|
||||
"text/template/parse",
|
||||
},
|
||||
"text/template": {
|
||||
"L4", "OS", "net/url", "text/template/parse",
|
||||
},
|
||||
|
||||
// Cgo.
|
||||
// If you add a dependency on CGO, you must add the package to
|
||||
// cgoPackages in cmd/dist/test.go.
|
||||
"runtime/cgo": {"L0", "C"},
|
||||
"CGO": {"C", "runtime/cgo"},
|
||||
|
||||
// Fake entry to satisfy the pseudo-import "C"
|
||||
// that shows up in programs that use cgo.
|
||||
"C": {},
|
||||
|
||||
// Race detector/MSan uses cgo.
|
||||
"runtime/race": {"C"},
|
||||
"runtime/msan": {"C"},
|
||||
|
||||
// Plan 9 alone needs io/ioutil and os.
|
||||
"os/user": {"L4", "CGO", "io/ioutil", "os", "syscall"},
|
||||
|
||||
// Basic networking.
|
||||
// Because net must be used by any package that wants to
|
||||
// do networking portably, it must have a small dependency set: just L0+basic os.
|
||||
"net": {
|
||||
"L0", "CGO",
|
||||
"context", "math/rand", "os", "reflect", "sort", "syscall", "time",
|
||||
"internal/nettrace", "internal/poll",
|
||||
"internal/syscall/windows", "internal/singleflight", "internal/race",
|
||||
"golang_org/x/net/lif", "golang_org/x/net/route",
|
||||
},
|
||||
|
||||
// NET enables use of basic network-related packages.
|
||||
"NET": {
|
||||
"net",
|
||||
"mime",
|
||||
"net/textproto",
|
||||
"net/url",
|
||||
},
|
||||
|
||||
// Uses of networking.
|
||||
"log/syslog": {"L4", "OS", "net"},
|
||||
"net/mail": {"L4", "NET", "OS", "mime"},
|
||||
"net/textproto": {"L4", "OS", "net"},
|
||||
|
||||
// Core crypto.
|
||||
"crypto/aes": {"L3"},
|
||||
"crypto/des": {"L3"},
|
||||
"crypto/hmac": {"L3"},
|
||||
"crypto/md5": {"L3"},
|
||||
"crypto/rc4": {"L3"},
|
||||
"crypto/sha1": {"L3"},
|
||||
"crypto/sha256": {"L3"},
|
||||
"crypto/sha512": {"L3"},
|
||||
|
||||
"CRYPTO": {
|
||||
"crypto/aes",
|
||||
"crypto/des",
|
||||
"crypto/hmac",
|
||||
"crypto/md5",
|
||||
"crypto/rc4",
|
||||
"crypto/sha1",
|
||||
"crypto/sha256",
|
||||
"crypto/sha512",
|
||||
"golang_org/x/crypto/chacha20poly1305",
|
||||
"golang_org/x/crypto/curve25519",
|
||||
"golang_org/x/crypto/poly1305",
|
||||
},
|
||||
|
||||
// Random byte, number generation.
|
||||
// This would be part of core crypto except that it imports
|
||||
// math/big, which imports fmt.
|
||||
"crypto/rand": {"L4", "CRYPTO", "OS", "math/big", "syscall", "internal/syscall/unix"},
|
||||
|
||||
// Mathematical crypto: dependencies on fmt (L4) and math/big.
|
||||
// We could avoid some of the fmt, but math/big imports fmt anyway.
|
||||
"crypto/dsa": {"L4", "CRYPTO", "math/big"},
|
||||
"crypto/ecdsa": {"L4", "CRYPTO", "crypto/elliptic", "math/big", "encoding/asn1"},
|
||||
"crypto/elliptic": {"L4", "CRYPTO", "math/big"},
|
||||
"crypto/rsa": {"L4", "CRYPTO", "crypto/rand", "math/big"},
|
||||
|
||||
"CRYPTO-MATH": {
|
||||
"CRYPTO",
|
||||
"crypto/dsa",
|
||||
"crypto/ecdsa",
|
||||
"crypto/elliptic",
|
||||
"crypto/rand",
|
||||
"crypto/rsa",
|
||||
"encoding/asn1",
|
||||
"math/big",
|
||||
},
|
||||
|
||||
// SSL/TLS.
|
||||
"crypto/tls": {
|
||||
"L4", "CRYPTO-MATH", "OS",
|
||||
"container/list", "crypto/x509", "encoding/pem", "net", "syscall",
|
||||
},
|
||||
"crypto/x509": {
|
||||
"L4", "CRYPTO-MATH", "OS", "CGO",
|
||||
"crypto/x509/pkix", "encoding/pem", "encoding/hex", "net", "os/user", "syscall",
|
||||
},
|
||||
"crypto/x509/pkix": {"L4", "CRYPTO-MATH"},
|
||||
|
||||
// Simple net+crypto-aware packages.
|
||||
"mime/multipart": {"L4", "OS", "mime", "crypto/rand", "net/textproto", "mime/quotedprintable"},
|
||||
"net/smtp": {"L4", "CRYPTO", "NET", "crypto/tls"},
|
||||
|
||||
// HTTP, kingpin of dependencies.
|
||||
"net/http": {
|
||||
"L4", "NET", "OS",
|
||||
"compress/gzip",
|
||||
"container/list",
|
||||
"context",
|
||||
"crypto/rand",
|
||||
"crypto/tls",
|
||||
"golang_org/x/net/http2/hpack",
|
||||
"golang_org/x/net/idna",
|
||||
"golang_org/x/net/lex/httplex",
|
||||
"golang_org/x/net/proxy",
|
||||
"golang_org/x/text/unicode/norm",
|
||||
"golang_org/x/text/width",
|
||||
"internal/nettrace",
|
||||
"mime/multipart",
|
||||
"net/http/httptrace",
|
||||
"net/http/internal",
|
||||
"runtime/debug",
|
||||
},
|
||||
"net/http/internal": {"L4"},
|
||||
"net/http/httptrace": {"context", "crypto/tls", "internal/nettrace", "net", "reflect", "time"},
|
||||
|
||||
// HTTP-using packages.
|
||||
"expvar": {"L4", "OS", "encoding/json", "net/http"},
|
||||
"net/http/cgi": {"L4", "NET", "OS", "crypto/tls", "net/http", "regexp"},
|
||||
"net/http/cookiejar": {"L4", "NET", "net/http"},
|
||||
"net/http/fcgi": {"L4", "NET", "OS", "context", "net/http", "net/http/cgi"},
|
||||
"net/http/httptest": {"L4", "NET", "OS", "crypto/tls", "flag", "net/http", "net/http/internal", "crypto/x509"},
|
||||
"net/http/httputil": {"L4", "NET", "OS", "context", "net/http", "net/http/internal"},
|
||||
"net/http/pprof": {"L4", "OS", "html/template", "net/http", "runtime/pprof", "runtime/trace"},
|
||||
"net/rpc": {"L4", "NET", "encoding/gob", "html/template", "net/http"},
|
||||
"net/rpc/jsonrpc": {"L4", "NET", "encoding/json", "net/rpc"},
|
||||
}
|
||||
|
||||
// isMacro reports whether p is a package dependency macro
|
||||
// (uppercase name).
|
||||
func isMacro(p string) bool {
|
||||
return 'A' <= p[0] && p[0] <= 'Z'
|
||||
}
|
||||
|
||||
func allowed(pkg string) map[string]bool {
|
||||
m := map[string]bool{}
|
||||
var allow func(string)
|
||||
allow = func(p string) {
|
||||
if m[p] {
|
||||
return
|
||||
}
|
||||
m[p] = true // set even for macros, to avoid loop on cycle
|
||||
|
||||
// Upper-case names are macro-expanded.
|
||||
if isMacro(p) {
|
||||
for _, pp := range pkgDeps[p] {
|
||||
allow(pp)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, pp := range pkgDeps[pkg] {
|
||||
allow(pp)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// listStdPkgs returns the same list of packages as "go list std".
|
||||
func listStdPkgs(goroot string) ([]string, error) {
|
||||
// Based on cmd/go's matchPackages function.
|
||||
var pkgs []string
|
||||
|
||||
src := filepath.Join(goroot, "src") + string(filepath.Separator)
|
||||
walkFn := func(path string, fi os.FileInfo, err error) error {
|
||||
if err != nil || !fi.IsDir() || path == src {
|
||||
return nil
|
||||
}
|
||||
|
||||
base := filepath.Base(path)
|
||||
if strings.HasPrefix(base, ".") || strings.HasPrefix(base, "_") || base == "testdata" {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
|
||||
name := filepath.ToSlash(path[len(src):])
|
||||
if name == "builtin" || name == "cmd" || strings.Contains(name, "golang_org") {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
|
||||
pkgs = append(pkgs, name)
|
||||
return nil
|
||||
}
|
||||
if err := filepath.Walk(src, walkFn); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pkgs, nil
|
||||
}
|
||||
|
||||
// This test does not function well in travis under different go versions for some reason.
|
||||
//
|
||||
// func TestDependencies(t *testing.T) {
|
||||
// iOS := runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64")
|
||||
// if runtime.GOOS == "nacl" || iOS {
|
||||
// // Tests run in a limited file system and we do not
|
||||
// // provide access to every source file.
|
||||
// t.Skipf("skipping on %s/%s, missing full GOROOT", runtime.GOOS, runtime.GOARCH)
|
||||
// }
|
||||
|
||||
// ctxt := Default
|
||||
// all, err := listStdPkgs(ctxt.GOROOT)
|
||||
// if err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
// sort.Strings(all)
|
||||
|
||||
// for _, pkg := range all {
|
||||
// imports, err := findImports(pkg)
|
||||
// if err != nil {
|
||||
// t.Error(err)
|
||||
// continue
|
||||
// }
|
||||
// ok := allowed(pkg)
|
||||
// var bad []string
|
||||
// for _, imp := range imports {
|
||||
// if !ok[imp] {
|
||||
// bad = append(bad, imp)
|
||||
// }
|
||||
// }
|
||||
// if bad != nil {
|
||||
// t.Errorf("unexpected dependency: %s imports %v", pkg, bad)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
var buildIgnore = []byte("\n// +build ignore")
|
||||
|
||||
func findImports(pkg string) ([]string, error) {
|
||||
dir := filepath.Join(Default.GOROOT, "src", pkg)
|
||||
files, err := ioutil.ReadDir(dir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var imports []string
|
||||
var haveImport = map[string]bool{}
|
||||
for _, file := range files {
|
||||
name := file.Name()
|
||||
if !strings.HasSuffix(name, ".go") || strings.HasSuffix(name, "_test.go") {
|
||||
continue
|
||||
}
|
||||
f, err := os.Open(filepath.Join(dir, name))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var imp []string
|
||||
data, err := readImports(f, false, &imp)
|
||||
f.Close()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("reading %v: %v", name, err)
|
||||
}
|
||||
if bytes.Contains(data, buildIgnore) {
|
||||
continue
|
||||
}
|
||||
for _, quoted := range imp {
|
||||
path, err := strconv.Unquote(quoted)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if !haveImport[path] {
|
||||
haveImport[path] = true
|
||||
imports = append(imports, path)
|
||||
}
|
||||
}
|
||||
}
|
||||
sort.Strings(imports)
|
||||
return imports, nil
|
||||
}
|
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
|
@ -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
|
||||
}
|
226
vendor/github.com/magefile/mage/build/read_test.go
generated
vendored
Normal file
|
@ -0,0 +1,226 @@
|
|||
// 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 (
|
||||
"io"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const quote = "`"
|
||||
|
||||
type readTest struct {
|
||||
// Test input contains ℙ where readImports should stop.
|
||||
in string
|
||||
err string
|
||||
}
|
||||
|
||||
var readImportsTests = []readTest{
|
||||
{
|
||||
`package p`,
|
||||
"",
|
||||
},
|
||||
{
|
||||
`package p; import "x"`,
|
||||
"",
|
||||
},
|
||||
{
|
||||
`package p; import . "x"`,
|
||||
"",
|
||||
},
|
||||
{
|
||||
`package p; import "x";ℙvar x = 1`,
|
||||
"",
|
||||
},
|
||||
{
|
||||
`package p
|
||||
|
||||
// comment
|
||||
|
||||
import "x"
|
||||
import _ "x"
|
||||
import a "x"
|
||||
|
||||
/* comment */
|
||||
|
||||
import (
|
||||
"x" /* comment */
|
||||
_ "x"
|
||||
a "x" // comment
|
||||
` + quote + `x` + quote + `
|
||||
_ /*comment*/ ` + quote + `x` + quote + `
|
||||
a ` + quote + `x` + quote + `
|
||||
)
|
||||
import (
|
||||
)
|
||||
import ()
|
||||
import()import()import()
|
||||
import();import();import()
|
||||
|
||||
ℙvar x = 1
|
||||
`,
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
||||
var readCommentsTests = []readTest{
|
||||
{
|
||||
`ℙpackage p`,
|
||||
"",
|
||||
},
|
||||
{
|
||||
`ℙpackage p; import "x"`,
|
||||
"",
|
||||
},
|
||||
{
|
||||
`ℙpackage p; import . "x"`,
|
||||
"",
|
||||
},
|
||||
{
|
||||
`// foo
|
||||
|
||||
/* bar */
|
||||
|
||||
/* quux */ // baz
|
||||
|
||||
/*/ zot */
|
||||
|
||||
// asdf
|
||||
ℙHello, world`,
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
||||
func testRead(t *testing.T, tests []readTest, read func(io.Reader) ([]byte, error)) {
|
||||
for i, tt := range tests {
|
||||
var in, testOut string
|
||||
j := strings.Index(tt.in, "ℙ")
|
||||
if j < 0 {
|
||||
in = tt.in
|
||||
testOut = tt.in
|
||||
} else {
|
||||
in = tt.in[:j] + tt.in[j+len("ℙ"):]
|
||||
testOut = tt.in[:j]
|
||||
}
|
||||
r := strings.NewReader(in)
|
||||
buf, err := read(r)
|
||||
if err != nil {
|
||||
if tt.err == "" {
|
||||
t.Errorf("#%d: err=%q, expected success (%q)", i, err, string(buf))
|
||||
continue
|
||||
}
|
||||
if !strings.Contains(err.Error(), tt.err) {
|
||||
t.Errorf("#%d: err=%q, expected %q", i, err, tt.err)
|
||||
continue
|
||||
}
|
||||
continue
|
||||
}
|
||||
if err == nil && tt.err != "" {
|
||||
t.Errorf("#%d: success, expected %q", i, tt.err)
|
||||
continue
|
||||
}
|
||||
|
||||
out := string(buf)
|
||||
if out != testOut {
|
||||
t.Errorf("#%d: wrong output:\nhave %q\nwant %q\n", i, out, testOut)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadImports(t *testing.T) {
|
||||
testRead(t, readImportsTests, func(r io.Reader) ([]byte, error) { return readImports(r, true, nil) })
|
||||
}
|
||||
|
||||
func TestReadComments(t *testing.T) {
|
||||
testRead(t, readCommentsTests, readComments)
|
||||
}
|
||||
|
||||
var readFailuresTests = []readTest{
|
||||
{
|
||||
`package`,
|
||||
"syntax error",
|
||||
},
|
||||
{
|
||||
"package p\n\x00\nimport `math`\n",
|
||||
"unexpected NUL in input",
|
||||
},
|
||||
{
|
||||
`package p; import`,
|
||||
"syntax error",
|
||||
},
|
||||
{
|
||||
`package p; import "`,
|
||||
"syntax error",
|
||||
},
|
||||
{
|
||||
"package p; import ` \n\n",
|
||||
"syntax error",
|
||||
},
|
||||
{
|
||||
`package p; import "x`,
|
||||
"syntax error",
|
||||
},
|
||||
{
|
||||
`package p; import _`,
|
||||
"syntax error",
|
||||
},
|
||||
{
|
||||
`package p; import _ "`,
|
||||
"syntax error",
|
||||
},
|
||||
{
|
||||
`package p; import _ "x`,
|
||||
"syntax error",
|
||||
},
|
||||
{
|
||||
`package p; import .`,
|
||||
"syntax error",
|
||||
},
|
||||
{
|
||||
`package p; import . "`,
|
||||
"syntax error",
|
||||
},
|
||||
{
|
||||
`package p; import . "x`,
|
||||
"syntax error",
|
||||
},
|
||||
{
|
||||
`package p; import (`,
|
||||
"syntax error",
|
||||
},
|
||||
{
|
||||
`package p; import ("`,
|
||||
"syntax error",
|
||||
},
|
||||
{
|
||||
`package p; import ("x`,
|
||||
"syntax error",
|
||||
},
|
||||
{
|
||||
`package p; import ("x"`,
|
||||
"syntax error",
|
||||
},
|
||||
}
|
||||
|
||||
func TestReadFailures(t *testing.T) {
|
||||
// Errors should be reported (true arg to readImports).
|
||||
testRead(t, readFailuresTests, func(r io.Reader) ([]byte, error) { return readImports(r, true, nil) })
|
||||
}
|
||||
|
||||
func TestReadFailuresIgnored(t *testing.T) {
|
||||
// Syntax errors should not be reported (false arg to readImports).
|
||||
// Instead, entire file should be the output and no error.
|
||||
// Convert tests not to return syntax errors.
|
||||
tests := make([]readTest, len(readFailuresTests))
|
||||
copy(tests, readFailuresTests)
|
||||
for i := range tests {
|
||||
tt := &tests[i]
|
||||
if !strings.Contains(tt.err, "NUL") {
|
||||
tt.err = ""
|
||||
}
|
||||
}
|
||||
testRead(t, tests, func(r io.Reader) ([]byte, error) { return readImports(r, false, nil) })
|
||||
}
|
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 "
|
62
vendor/github.com/magefile/mage/build/syslist_test.go
generated
vendored
Normal file
|
@ -0,0 +1,62 @@
|
|||
// 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
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
thisOS = runtime.GOOS
|
||||
thisArch = runtime.GOARCH
|
||||
otherOS = anotherOS()
|
||||
otherArch = anotherArch()
|
||||
)
|
||||
|
||||
func anotherOS() string {
|
||||
if thisOS != "darwin" {
|
||||
return "darwin"
|
||||
}
|
||||
return "linux"
|
||||
}
|
||||
|
||||
func anotherArch() string {
|
||||
if thisArch != "amd64" {
|
||||
return "amd64"
|
||||
}
|
||||
return "386"
|
||||
}
|
||||
|
||||
type GoodFileTest struct {
|
||||
name string
|
||||
result bool
|
||||
}
|
||||
|
||||
var tests = []GoodFileTest{
|
||||
{"file.go", true},
|
||||
{"file.c", true},
|
||||
{"file_foo.go", true},
|
||||
{"file_" + thisArch + ".go", true},
|
||||
{"file_" + otherArch + ".go", false},
|
||||
{"file_" + thisOS + ".go", true},
|
||||
{"file_" + otherOS + ".go", false},
|
||||
{"file_" + thisOS + "_" + thisArch + ".go", true},
|
||||
{"file_" + otherOS + "_" + thisArch + ".go", false},
|
||||
{"file_" + thisOS + "_" + otherArch + ".go", false},
|
||||
{"file_" + otherOS + "_" + otherArch + ".go", false},
|
||||
{"file_foo_" + thisArch + ".go", true},
|
||||
{"file_foo_" + otherArch + ".go", false},
|
||||
{"file_" + thisOS + ".c", true},
|
||||
{"file_" + otherOS + ".c", false},
|
||||
}
|
||||
|
||||
func TestGoodOSArch(t *testing.T) {
|
||||
for _, test := range tests {
|
||||
if Default.goodOSArchFile(test.name, make(map[string]bool)) != test.result {
|
||||
t.Fatalf("goodOSArchFile(%q) != %v", test.name, test.result)
|
||||
}
|
||||
}
|
||||
}
|
0
vendor/github.com/magefile/mage/build/testdata/empty/dummy
generated
vendored
Normal file
5
vendor/github.com/magefile/mage/build/testdata/multi/file.go
generated
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
// Test data - not compiled.
|
||||
|
||||
package main
|
||||
|
||||
func main() {}
|
5
vendor/github.com/magefile/mage/build/testdata/multi/file_appengine.go
generated
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
// Test data - not compiled.
|
||||
|
||||
package test_package
|
||||
|
||||
func init() {}
|
5
vendor/github.com/magefile/mage/build/testdata/other/file/file.go
generated
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
// Test data - not compiled.
|
||||
|
||||
package file
|
||||
|
||||
func F() {}
|
11
vendor/github.com/magefile/mage/build/testdata/other/main.go
generated
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
// Test data - not compiled.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"./file"
|
||||
)
|
||||
|
||||
func main() {
|
||||
file.F()
|
||||
}
|
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,
|
||||
}
|
34
vendor/github.com/magefile/mage/contrib_test.go
generated
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGoFormatted(t *testing.T) {
|
||||
s, err := run("gofmt", "-l", ".")
|
||||
if s != "" {
|
||||
t.Fatalf("the following files are not gofmt'ed:\n%s", s)
|
||||
}
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGoVet(t *testing.T) {
|
||||
s, err := run("go", "vet", "./...")
|
||||
if s != "" {
|
||||
t.Fatalf("go vet fails with:\n%s", s)
|
||||
}
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func run(cmd string, args ...string) (string, error) {
|
||||
c := exec.Command(cmd, args...)
|
||||
c.Env = os.Environ()
|
||||
b, err := c.CombinedOutput()
|
||||
return string(b), err
|
||||
}
|
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")
|
||||
}
|
||||
`
|
399
vendor/github.com/magefile/mage/mage/main.go
generated
vendored
Normal file
|
@ -0,0 +1,399 @@
|
|||
package mage
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"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"
|
||||
)
|
||||
|
||||
// mageVer is used when hashing the output binary to ensure that we get a new
|
||||
// binary if we use a differernt version of mage.
|
||||
const mageVer = "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"
|
||||
)
|
||||
|
||||
// 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, mageInit, showVersion, 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
|
||||
}
|
||||
|
||||
if showVersion {
|
||||
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
|
||||
}
|
||||
if mageInit {
|
||||
if err := generateInit(dir); err != nil {
|
||||
log.Println("Error:", err)
|
||||
return 1
|
||||
}
|
||||
log.Println(initFile, "created")
|
||||
return 0
|
||||
}
|
||||
|
||||
return Invoke(inv)
|
||||
}
|
||||
|
||||
// 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, mageInit, showVersion bool, 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.BoolVar(&mageInit, "init", false, "create a starting template if no mage files exist")
|
||||
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")
|
||||
fs.BoolVar(&showVersion, "version", false, "show version info for the mage binary")
|
||||
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, mageInit, showVersion, err
|
||||
}
|
||||
if err == nil && inv.Help && len(fs.Args()) == 0 {
|
||||
fs.Usage()
|
||||
// tell upstream, to just exit
|
||||
return inv, mageInit, showVersion, flag.ErrHelp
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
numFlags := 0
|
||||
if inv.Help {
|
||||
numFlags++
|
||||
}
|
||||
if mageInit {
|
||||
numFlags++
|
||||
}
|
||||
if showVersion {
|
||||
numFlags++
|
||||
}
|
||||
|
||||
if numFlags > 1 {
|
||||
return inv, mageInit, showVersion, errors.New("-h, -init, and -version cannot be used simultaneously")
|
||||
}
|
||||
|
||||
inv.Args = fs.Args()
|
||||
if inv.Help && len(inv.Args) > 1 {
|
||||
return inv, mageInit, showVersion, errors.New("-h can only show help for a single target")
|
||||
}
|
||||
|
||||
return inv, mageInit, showVersion, 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
|
||||
}
|
||||
|
||||
// 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,
|
||||
}
|
||||
|
||||
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, "") + mageVer))
|
||||
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())
|
||||
}
|
479
vendor/github.com/magefile/mage/mage/main_test.go
generated
vendored
Normal file
|
@ -0,0 +1,479 @@
|
|||
package mage
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/magefile/mage/build"
|
||||
"github.com/magefile/mage/mg"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
os.Exit(testmain(m))
|
||||
}
|
||||
|
||||
func testmain(m *testing.M) int {
|
||||
// ensure we write our temporary binaries to a directory that we'll delete
|
||||
// after running tests.
|
||||
dir := "./testing"
|
||||
abs, err := filepath.Abs(dir)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err := os.Setenv(mg.CacheEnv, abs); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err := os.Mkdir(dir, 0700); err != nil {
|
||||
if os.IsExist(err) {
|
||||
os.RemoveAll(dir)
|
||||
} else {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
return m.Run()
|
||||
}
|
||||
|
||||
func TestGoRun(t *testing.T) {
|
||||
c := exec.Command("go", "run", "main.go")
|
||||
c.Dir = "./testdata"
|
||||
c.Env = os.Environ()
|
||||
b, err := c.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Error("error:", err)
|
||||
}
|
||||
actual := string(b)
|
||||
expected := "stuff\n"
|
||||
if actual != expected {
|
||||
t.Fatalf("expected %q, but got %q", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerbose(t *testing.T) {
|
||||
stderr := &bytes.Buffer{}
|
||||
stdout := &bytes.Buffer{}
|
||||
inv := Invocation{
|
||||
Dir: "./testdata",
|
||||
Stdout: stdout,
|
||||
Stderr: stderr,
|
||||
Args: []string{"testverbose"},
|
||||
}
|
||||
|
||||
code := Invoke(inv)
|
||||
if code != 0 {
|
||||
t.Errorf("expected to exit with code 0, but got %v", code)
|
||||
}
|
||||
actual := stdout.String()
|
||||
expected := ""
|
||||
if actual != expected {
|
||||
t.Fatalf("expected %q, but got %q", expected, actual)
|
||||
}
|
||||
stderr.Reset()
|
||||
stdout.Reset()
|
||||
inv.Verbose = true
|
||||
code = Invoke(inv)
|
||||
if code != 0 {
|
||||
t.Errorf("expected to exit with code 0, but got %v", code)
|
||||
}
|
||||
|
||||
actual = stderr.String()
|
||||
expected = "Running target: TestVerbose\nhi!\n"
|
||||
if actual != expected {
|
||||
t.Fatalf("expected %q, but got %q", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerboseEnv(t *testing.T) {
|
||||
os.Setenv("MAGE_VERBOSE", "true")
|
||||
|
||||
stdout := &bytes.Buffer{}
|
||||
inv, _, _, err := Parse(stdout, []string{})
|
||||
if err != nil {
|
||||
t.Fatal("unexpected error", err)
|
||||
}
|
||||
|
||||
expected := true
|
||||
|
||||
if inv.Verbose != true {
|
||||
t.Fatalf("expected %t, but got %t ", expected, inv.Verbose)
|
||||
}
|
||||
|
||||
os.Unsetenv("MAGE_VERBOSE")
|
||||
}
|
||||
|
||||
func TestList(t *testing.T) {
|
||||
stdout := &bytes.Buffer{}
|
||||
inv := Invocation{
|
||||
Dir: "./testdata/list",
|
||||
Stdout: stdout,
|
||||
Stderr: ioutil.Discard,
|
||||
List: true,
|
||||
}
|
||||
|
||||
code := Invoke(inv)
|
||||
if code != 0 {
|
||||
t.Errorf("expected to exit with code 0, but got %v", code)
|
||||
}
|
||||
actual := stdout.String()
|
||||
expected := `
|
||||
Targets:
|
||||
somePig* This is the synopsis for SomePig.
|
||||
testVerbose
|
||||
|
||||
* default target
|
||||
`[1:]
|
||||
|
||||
if actual != expected {
|
||||
t.Logf("expected: %q", expected)
|
||||
t.Logf(" actual: %q", actual)
|
||||
t.Fatalf("expected:\n%v\n\ngot:\n%v", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNoArgNoDefaultList(t *testing.T) {
|
||||
stdout := &bytes.Buffer{}
|
||||
stderr := &bytes.Buffer{}
|
||||
inv := Invocation{
|
||||
Dir: "testdata/no_default",
|
||||
Stdout: stdout,
|
||||
Stderr: stderr,
|
||||
}
|
||||
code := Invoke(inv)
|
||||
if code != 0 {
|
||||
t.Errorf("expected to exit with code 0, but got %v", code)
|
||||
}
|
||||
if err := stderr.String(); err != "" {
|
||||
t.Errorf("unexpected stderr output:\n%s", err)
|
||||
}
|
||||
actual := stdout.String()
|
||||
expected := `
|
||||
Targets:
|
||||
bazBuz Prints out 'BazBuz'.
|
||||
fooBar Prints out 'FooBar'.
|
||||
`[1:]
|
||||
if actual != expected {
|
||||
t.Fatalf("expected:\n%q\n\ngot:\n%q", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTargetError(t *testing.T) {
|
||||
stderr := &bytes.Buffer{}
|
||||
inv := Invocation{
|
||||
Dir: "./testdata",
|
||||
Stdout: ioutil.Discard,
|
||||
Stderr: stderr,
|
||||
Args: []string{"returnsnonnilerror"},
|
||||
}
|
||||
code := Invoke(inv)
|
||||
if code != 1 {
|
||||
t.Fatalf("expected 1, but got %v", code)
|
||||
}
|
||||
actual := stderr.String()
|
||||
expected := "Error: bang!\n"
|
||||
if actual != expected {
|
||||
t.Fatalf("expected %q, but got %q", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStdinCopy(t *testing.T) {
|
||||
stdout := &bytes.Buffer{}
|
||||
stdin := strings.NewReader("hi!")
|
||||
inv := Invocation{
|
||||
Dir: "./testdata",
|
||||
Stderr: ioutil.Discard,
|
||||
Stdout: stdout,
|
||||
Stdin: stdin,
|
||||
Args: []string{"CopyStdin"},
|
||||
}
|
||||
code := Invoke(inv)
|
||||
if code != 0 {
|
||||
t.Fatalf("expected 0, but got %v", code)
|
||||
}
|
||||
actual := stdout.String()
|
||||
expected := "hi!"
|
||||
if actual != expected {
|
||||
t.Fatalf("expected %q, but got %q", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTargetPanics(t *testing.T) {
|
||||
stderr := &bytes.Buffer{}
|
||||
inv := Invocation{
|
||||
Dir: "./testdata",
|
||||
Stdout: ioutil.Discard,
|
||||
Stderr: stderr,
|
||||
Args: []string{"panics"},
|
||||
}
|
||||
code := Invoke(inv)
|
||||
if code != 1 {
|
||||
t.Fatalf("expected 1, but got %v", code)
|
||||
}
|
||||
actual := stderr.String()
|
||||
expected := "Error: boom!\n"
|
||||
if actual != expected {
|
||||
t.Fatalf("expected %q, but got %q", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPanicsErr(t *testing.T) {
|
||||
stderr := &bytes.Buffer{}
|
||||
inv := Invocation{
|
||||
Dir: "./testdata",
|
||||
Stdout: ioutil.Discard,
|
||||
Stderr: stderr,
|
||||
Args: []string{"panicserr"},
|
||||
}
|
||||
code := Invoke(inv)
|
||||
if code != 1 {
|
||||
t.Fatalf("expected 1, but got %v", code)
|
||||
}
|
||||
actual := stderr.String()
|
||||
expected := "Error: kaboom!\n"
|
||||
if actual != expected {
|
||||
t.Fatalf("expected %q, but got %q", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
// ensure we include the hash of the mainfile template in determining the
|
||||
// executable name to run, so we automatically create a new exe if the template
|
||||
// changes.
|
||||
func TestHashTemplate(t *testing.T) {
|
||||
templ := tpl
|
||||
defer func() { tpl = templ }()
|
||||
name, err := ExeName([]string{"./testdata/func.go", "./testdata/command.go"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tpl = "some other template"
|
||||
changed, err := ExeName([]string{"./testdata/func.go", "./testdata/command.go"})
|
||||
if changed == name {
|
||||
t.Fatal("expected executable name to chage if template changed")
|
||||
}
|
||||
}
|
||||
|
||||
// Test if the -keep flag does keep the mainfile around after running
|
||||
func TestKeepFlag(t *testing.T) {
|
||||
buildFile := fmt.Sprintf("./testdata/keep_flag/%s", mainfile)
|
||||
os.Remove(buildFile)
|
||||
defer os.Remove(buildFile)
|
||||
w := tLogWriter{t}
|
||||
|
||||
inv := Invocation{
|
||||
Dir: "./testdata/keep_flag",
|
||||
Stdout: w,
|
||||
Stderr: w,
|
||||
List: true,
|
||||
Keep: true,
|
||||
Force: true, // need force so we always regenerate
|
||||
}
|
||||
code := Invoke(inv)
|
||||
if code != 0 {
|
||||
t.Fatalf("expected code 0, but got %v", code)
|
||||
}
|
||||
|
||||
if _, err := os.Stat(buildFile); err != nil {
|
||||
t.Fatalf("expected file %q to exist but got err, %v", buildFile, err)
|
||||
}
|
||||
}
|
||||
|
||||
type tLogWriter struct {
|
||||
*testing.T
|
||||
}
|
||||
|
||||
func (t tLogWriter) Write(b []byte) (n int, err error) {
|
||||
t.Log(string(b))
|
||||
return len(b), nil
|
||||
}
|
||||
|
||||
// Test if generated mainfile references anything other than the stdlib
|
||||
func TestOnlyStdLib(t *testing.T) {
|
||||
buildFile := fmt.Sprintf("./testdata/onlyStdLib/%s", mainfile)
|
||||
os.Remove(buildFile)
|
||||
defer os.Remove(buildFile)
|
||||
|
||||
w := tLogWriter{t}
|
||||
|
||||
inv := Invocation{
|
||||
Dir: "./testdata/onlyStdLib",
|
||||
Stdout: w,
|
||||
Stderr: w,
|
||||
List: true,
|
||||
Keep: true,
|
||||
Force: true, // need force so we always regenerate
|
||||
Verbose: true,
|
||||
}
|
||||
code := Invoke(inv)
|
||||
if code != 0 {
|
||||
t.Fatalf("expected code 0, but got %v", code)
|
||||
}
|
||||
|
||||
if _, err := os.Stat(buildFile); err != nil {
|
||||
t.Fatalf("expected file %q to exist but got err, %v", buildFile, err)
|
||||
}
|
||||
|
||||
fset := &token.FileSet{}
|
||||
// Parse src but stop after processing the imports.
|
||||
f, err := parser.ParseFile(fset, buildFile, nil, parser.ImportsOnly)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
// Print the imports from the file's AST.
|
||||
for _, s := range f.Imports {
|
||||
// the path value comes in as a quoted string, i.e. literally \"context\"
|
||||
path := strings.Trim(s.Path.Value, "\"")
|
||||
pkg, err := build.Default.Import(path, "./testdata/keep_flag", build.FindOnly)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !filepath.HasPrefix(pkg.Dir, build.Default.GOROOT) {
|
||||
t.Errorf("import of non-stdlib package: %s", s.Path.Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMultipleTargets(t *testing.T) {
|
||||
var stderr, stdout bytes.Buffer
|
||||
inv := Invocation{
|
||||
Dir: "./testdata",
|
||||
Stdout: &stdout,
|
||||
Stderr: &stderr,
|
||||
Args: []string{"TestVerbose", "ReturnsNilError"},
|
||||
Verbose: true,
|
||||
}
|
||||
code := Invoke(inv)
|
||||
if code != 0 {
|
||||
t.Errorf("expected 0, but got %v", code)
|
||||
}
|
||||
actual := stderr.String()
|
||||
expected := "Running target: TestVerbose\nhi!\nRunning target: ReturnsNilError\n"
|
||||
if actual != expected {
|
||||
t.Errorf("expected %q, but got %q", expected, actual)
|
||||
}
|
||||
actual = stdout.String()
|
||||
expected = "stuff\n"
|
||||
if actual != expected {
|
||||
t.Errorf("expected %q, but got %q", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFirstTargetFails(t *testing.T) {
|
||||
var stderr, stdout bytes.Buffer
|
||||
inv := Invocation{
|
||||
Dir: "./testdata",
|
||||
Stdout: &stdout,
|
||||
Stderr: &stderr,
|
||||
Args: []string{"ReturnsNonNilError", "ReturnsNilError"},
|
||||
Verbose: true,
|
||||
}
|
||||
code := Invoke(inv)
|
||||
if code != 1 {
|
||||
t.Errorf("expected 1, but got %v", code)
|
||||
}
|
||||
actual := stderr.String()
|
||||
expected := "Running target: ReturnsNonNilError\nError: bang!\n"
|
||||
if actual != expected {
|
||||
t.Errorf("expected %q, but got %q", expected, actual)
|
||||
}
|
||||
actual = stdout.String()
|
||||
expected = ""
|
||||
if actual != expected {
|
||||
t.Errorf("expected %q, but got %q", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBadSecondTargets(t *testing.T) {
|
||||
var stderr, stdout bytes.Buffer
|
||||
inv := Invocation{
|
||||
Dir: "./testdata",
|
||||
Stdout: &stdout,
|
||||
Stderr: &stderr,
|
||||
Args: []string{"TestVerbose", "NotGonnaWork"},
|
||||
}
|
||||
code := Invoke(inv)
|
||||
if code != 2 {
|
||||
t.Errorf("expected 0, but got %v", code)
|
||||
}
|
||||
actual := stderr.String()
|
||||
expected := "Unknown target specified: NotGonnaWork\n"
|
||||
if actual != expected {
|
||||
t.Errorf("expected %q, but got %q", expected, actual)
|
||||
}
|
||||
actual = stdout.String()
|
||||
expected = ""
|
||||
if actual != expected {
|
||||
t.Errorf("expected %q, but got %q", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
buf := &bytes.Buffer{}
|
||||
inv, init, showVer, err := Parse(buf, []string{"-v", "build"})
|
||||
if err != nil {
|
||||
t.Fatal("unexpected error", err)
|
||||
}
|
||||
if init {
|
||||
t.Fatal("init should be false but was true")
|
||||
}
|
||||
if showVer {
|
||||
t.Fatal("showVersion should be false but was true")
|
||||
}
|
||||
if len(inv.Args) != 1 && inv.Args[0] != "build" {
|
||||
t.Fatalf("expected args to be %q but got %q", []string{"build"}, inv.Args)
|
||||
}
|
||||
if s := buf.String(); s != "" {
|
||||
t.Fatalf("expected no stdout output but got %q", s)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Test the timeout option
|
||||
func TestTimeout(t *testing.T) {
|
||||
stderr := &bytes.Buffer{}
|
||||
inv := Invocation{
|
||||
Dir: "./testdata/context",
|
||||
Stdout: ioutil.Discard,
|
||||
Stderr: stderr,
|
||||
Args: []string{"timeout"},
|
||||
Timeout: time.Duration(100 * time.Millisecond),
|
||||
}
|
||||
code := Invoke(inv)
|
||||
if code != 1 {
|
||||
t.Fatalf("expected 1, but got %v", code)
|
||||
}
|
||||
actual := stderr.String()
|
||||
expected := "Error: context deadline exceeded\n"
|
||||
|
||||
if actual != expected {
|
||||
t.Fatalf("expected %q, but got %q", expected, actual)
|
||||
}
|
||||
}
|
||||
func TestParseHelp(t *testing.T) {
|
||||
buf := &bytes.Buffer{}
|
||||
_, _, _, err := Parse(buf, []string{"-h"})
|
||||
if err != flag.ErrHelp {
|
||||
t.Fatal("unexpected error", err)
|
||||
}
|
||||
buf2 := &bytes.Buffer{}
|
||||
_, _, _, err = Parse(buf2, []string{"--help"})
|
||||
if err != flag.ErrHelp {
|
||||
t.Fatal("unexpected error", err)
|
||||
}
|
||||
s := buf.String()
|
||||
s2 := buf2.String()
|
||||
if s != s2 {
|
||||
t.Fatalf("expected -h and --help to produce same output, but got different.\n\n-h:\n%s\n\n--help:\n%s", s, s2)
|
||||
}
|
||||
}
|
180
vendor/github.com/magefile/mage/mage/template.go
generated
vendored
Normal file
|
@ -0,0 +1,180 @@
|
|||
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() {
|
||||
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 .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")
|
||||
fmt.Println({{printf "%q" .Comment}})
|
||||
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 .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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func list() 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
|
||||
}
|
||||
|
||||
func handleError(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)
|
||||
}
|
||||
}
|
||||
|
||||
func runTarget(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
|
||||
}
|
||||
}
|
||||
|
||||
var ctx context.Context
|
||||
var ctxCancel func()
|
||||
|
||||
func getContext() (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
|
||||
}
|
||||
|
||||
|
||||
|
||||
`
|
29
vendor/github.com/magefile/mage/mage/testdata/command.go
generated
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
// +build mage
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/magefile/mage/mg"
|
||||
)
|
||||
|
||||
// This should work as a default - even if it's in a different file
|
||||
var Default = ReturnsNilError
|
||||
|
||||
// this should not be a target because it returns a string
|
||||
func ReturnsString() string {
|
||||
fmt.Println("more stuff")
|
||||
return ""
|
||||
}
|
||||
|
||||
func TestVerbose() {
|
||||
log.Println("hi!")
|
||||
}
|
||||
|
||||
func ReturnsVoid() {
|
||||
mg.Deps(f)
|
||||
}
|
||||
|
||||
func f() {}
|
30
vendor/github.com/magefile/mage/mage/testdata/context/context.go
generated
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
// +build mage
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/magefile/mage/mg"
|
||||
)
|
||||
|
||||
// Returns a non-nil error.
|
||||
func TakesContextNoError(ctx context.Context) {
|
||||
deadline, _ := ctx.Deadline()
|
||||
fmt.Printf("Context timeout: %v\n", deadline)
|
||||
}
|
||||
|
||||
func Timeout(ctx context.Context) {
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
}
|
||||
|
||||
func TakesContextWithError(ctx context.Context) error {
|
||||
return errors.New("Something went sideways")
|
||||
}
|
||||
|
||||
func CtxDeps(ctx context.Context) {
|
||||
mg.CtxDeps(ctx, TakesContextNoError)
|
||||
}
|
10
vendor/github.com/magefile/mage/mage/testdata/error.go
generated
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
// +build mage
|
||||
|
||||
package main
|
||||
|
||||
import "errors"
|
||||
|
||||
// Returns a non-nil error.
|
||||
func ReturnsNonNilError() error {
|
||||
return errors.New("bang!")
|
||||
}
|
23
vendor/github.com/magefile/mage/mage/testdata/func.go
generated
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
// +build mage
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
// Synopsis for "returns" error.
|
||||
// And some more text.
|
||||
func ReturnsNilError() error {
|
||||
fmt.Println("stuff")
|
||||
return nil
|
||||
}
|
||||
|
||||
func CopyStdin() error {
|
||||
_, err := io.Copy(os.Stdout, os.Stdin)
|
||||
return err
|
||||
}
|
||||
|
||||
func nonexported() {}
|
5
vendor/github.com/magefile/mage/mage/testdata/keep_flag/magefile.go
generated
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
// +build mage
|
||||
|
||||
package main
|
||||
|
||||
func Noop() {}
|
29
vendor/github.com/magefile/mage/mage/testdata/list/command.go
generated
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
// +build mage
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/magefile/mage/mg"
|
||||
)
|
||||
|
||||
var Default = SomePig
|
||||
|
||||
// this should not be a target because it returns a string
|
||||
func ReturnsString() string {
|
||||
fmt.Println("more stuff")
|
||||
return ""
|
||||
}
|
||||
|
||||
func TestVerbose() {
|
||||
log.Println("hi!")
|
||||
}
|
||||
|
||||
// This is the synopsis for SomePig. There's more data that won't show up.
|
||||
func SomePig() {
|
||||
mg.Deps(f)
|
||||
}
|
||||
|
||||
func f() {}
|
13
vendor/github.com/magefile/mage/mage/testdata/main.go
generated
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/magefile/mage/mage"
|
||||
)
|
||||
|
||||
func main() {
|
||||
os.Exit(mage.Main())
|
||||
}
|
19
vendor/github.com/magefile/mage/mage/testdata/no_default/magefile.go
generated
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
// +build mage
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// No default so we can check the list().
|
||||
|
||||
// Prints out 'FooBar'.
|
||||
func FooBar() {
|
||||
fmt.Println("FooBar")
|
||||
}
|
||||
|
||||
// Prints out 'BazBuz'.
|
||||
func BazBuz() {
|
||||
fmt.Println("BazBuz")
|
||||
}
|
29
vendor/github.com/magefile/mage/mage/testdata/onlyStdLib/command.go
generated
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
// +build mage
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/magefile/mage/mg"
|
||||
)
|
||||
|
||||
var Default = SomePig
|
||||
|
||||
// this should not be a target because it returns a string
|
||||
func ReturnsString() string {
|
||||
fmt.Println("more stuff")
|
||||
return ""
|
||||
}
|
||||
|
||||
func TestVerbose() {
|
||||
log.Println("hi!")
|
||||
}
|
||||
|
||||
// This is the synopsis for SomePig. There's more data that won't show up.
|
||||
func SomePig() {
|
||||
mg.Deps(f)
|
||||
}
|
||||
|
||||
func f() {}
|
15
vendor/github.com/magefile/mage/mage/testdata/panic.go
generated
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
// +build mage
|
||||
|
||||
package main
|
||||
|
||||
import "errors"
|
||||
|
||||
// Function that panics.
|
||||
func Panics() {
|
||||
panic("boom!")
|
||||
}
|
||||
|
||||
// Error function that panics.
|
||||
func PanicsErr() error {
|
||||
panic(errors.New("kaboom!"))
|
||||
}
|
72
vendor/github.com/magefile/mage/magefile.go
generated
vendored
Normal file
|
@ -0,0 +1,72 @@
|
|||
//+build mage
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/magefile/mage/sh"
|
||||
)
|
||||
|
||||
// Runs "go install" for mage. This generates the version info the binary.
|
||||
func Build() error {
|
||||
ldf, err := flags()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return sh.Run("go", "install", "-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 {
|
||||
buf := &bytes.Buffer{}
|
||||
_, _ = sh.Exec(nil, buf, nil, "git", "describe", "--tags")
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// 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
|
@ -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
|
@ -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
|
||||
}
|
147
vendor/github.com/magefile/mage/mg/deps_test.go
generated
vendored
Normal file
|
@ -0,0 +1,147 @@
|
|||
package mg_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/magefile/mage/mg"
|
||||
)
|
||||
|
||||
func TestDepsRunOnce(t *testing.T) {
|
||||
done := make(chan struct{})
|
||||
f := func() {
|
||||
done <- struct{}{}
|
||||
}
|
||||
go mg.Deps(f, f)
|
||||
select {
|
||||
case <-done:
|
||||
// cool
|
||||
case <-time.After(time.Millisecond * 100):
|
||||
t.Fatal("func not run in a reasonable amount of time.")
|
||||
}
|
||||
select {
|
||||
case <-done:
|
||||
t.Fatal("func run twice!")
|
||||
case <-time.After(time.Millisecond * 100):
|
||||
// cool... this should be plenty of time for the goroutine to have run
|
||||
}
|
||||
}
|
||||
|
||||
func TestDepsOfDeps(t *testing.T) {
|
||||
ch := make(chan string, 3)
|
||||
// this->f->g->h
|
||||
h := func() {
|
||||
ch <- "h"
|
||||
}
|
||||
g := func() {
|
||||
mg.Deps(h)
|
||||
ch <- "g"
|
||||
}
|
||||
f := func() {
|
||||
mg.Deps(g)
|
||||
ch <- "f"
|
||||
}
|
||||
mg.Deps(f)
|
||||
|
||||
res := <-ch + <-ch + <-ch
|
||||
|
||||
if res != "hgf" {
|
||||
t.Fatal("expected h then g then f to run, but got " + res)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDepError(t *testing.T) {
|
||||
// TODO: this test is ugly and relies on implementation details. It should
|
||||
// be recreated as a full-stack test.
|
||||
|
||||
f := func() error {
|
||||
return errors.New("ouch!")
|
||||
}
|
||||
defer func() {
|
||||
err := recover()
|
||||
if err == nil {
|
||||
t.Fatal("expected panic, but didn't get one")
|
||||
}
|
||||
actual := fmt.Sprint(err)
|
||||
if "ouch!" != actual {
|
||||
t.Fatalf(`expected to get "ouch!" but got "%s"`, actual)
|
||||
}
|
||||
}()
|
||||
mg.Deps(f)
|
||||
}
|
||||
|
||||
func TestDepFatal(t *testing.T) {
|
||||
f := func() error {
|
||||
return mg.Fatal(99, "ouch!")
|
||||
}
|
||||
defer func() {
|
||||
v := recover()
|
||||
if v == nil {
|
||||
t.Fatal("expected panic, but didn't get one")
|
||||
}
|
||||
actual := fmt.Sprint(v)
|
||||
if "ouch!" != actual {
|
||||
t.Fatalf(`expected to get "ouch!" but got "%s"`, actual)
|
||||
}
|
||||
err, ok := v.(error)
|
||||
if !ok {
|
||||
t.Fatalf("expected recovered val to be error but was %T", v)
|
||||
}
|
||||
code := mg.ExitStatus(err)
|
||||
if code != 99 {
|
||||
t.Fatalf("Expected exit status 99, but got %v", code)
|
||||
}
|
||||
}()
|
||||
mg.Deps(f)
|
||||
}
|
||||
|
||||
func TestDepTwoFatal(t *testing.T) {
|
||||
f := func() error {
|
||||
return mg.Fatal(99, "ouch!")
|
||||
}
|
||||
g := func() error {
|
||||
return mg.Fatal(11, "bang!")
|
||||
}
|
||||
defer func() {
|
||||
v := recover()
|
||||
if v == nil {
|
||||
t.Fatal("expected panic, but didn't get one")
|
||||
}
|
||||
actual := fmt.Sprint(v)
|
||||
// order is non-deterministic, so check for both orders
|
||||
if "ouch!\nbang!" != actual && "bang!\nouch!" != actual {
|
||||
t.Fatalf(`expected to get "ouch!" and "bang!" but got "%s"`, actual)
|
||||
}
|
||||
err, ok := v.(error)
|
||||
if !ok {
|
||||
t.Fatalf("expected recovered val to be error but was %T", v)
|
||||
}
|
||||
code := mg.ExitStatus(err)
|
||||
// two different error codes returns, so we give up and just use error
|
||||
// code 1.
|
||||
if code != 1 {
|
||||
t.Fatalf("Expected exit status 1, but got %v", code)
|
||||
}
|
||||
}()
|
||||
mg.Deps(f, g)
|
||||
}
|
||||
|
||||
func TestDepWithUnhandledFunc(t *testing.T) {
|
||||
defer func() {
|
||||
err := recover()
|
||||
expected := "Invalid type for dependent function: func(string) string. Dependencies must be func(), func() error, func(context.Context) or func(context.Context) error"
|
||||
actual, ok := err.(error)
|
||||
if !ok {
|
||||
t.Fatalf("Expected type string from panic")
|
||||
}
|
||||
if actual.Error() != expected {
|
||||
t.Fatalf("Expected panic %v but got %v", expected, err)
|
||||
}
|
||||
}()
|
||||
var NotValid func(string) string = func(a string) string {
|
||||
return a
|
||||
}
|
||||
mg.Deps(NotValid)
|
||||
}
|
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()
|
||||
}
|
19
vendor/github.com/magefile/mage/mg/errors_test.go
generated
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
package mg
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestFatalExit(t *testing.T) {
|
||||
expected := 99
|
||||
code := ExitStatus(Fatal(expected))
|
||||
if code != expected {
|
||||
t.Fatalf("Expected code %v but got %v", expected, code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFatalfExit(t *testing.T) {
|
||||
expected := 99
|
||||
code := ExitStatus(Fatalf(expected, "boo!"))
|
||||
if code != expected {
|
||||
t.Fatalf("Expected code %v but got %v", expected, code)
|
||||
}
|
||||
}
|
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
|
@ -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
|
@ -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))
|
||||
}
|
271
vendor/github.com/magefile/mage/parse/parse.go
generated
vendored
Normal file
|
@ -0,0 +1,271 @@
|
|||
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
|
||||
}
|
||||
|
||||
// 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: doc.Synopsis(f.Doc),
|
||||
IsError: typ == mgTypes.ErrorType || typ == mgTypes.ContextErrorType,
|
||||
IsContext: typ == mgTypes.ContextVoidType || typ == mgTypes.ContextErrorType,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
setDefault(p, pi, info)
|
||||
|
||||
return pi, nil
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
58
vendor/github.com/magefile/mage/parse/parse_test.go
generated
vendored
Normal file
|
@ -0,0 +1,58 @@
|
|||
package parse
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
info, err := Package("./testdata", []string{"func.go", "command.go"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
expected := []Function{
|
||||
{
|
||||
Name: "ReturnsNilError",
|
||||
IsError: true,
|
||||
Comment: "Synopsis for \"returns\" error.\nAnd some more text.\n",
|
||||
Synopsis: `Synopsis for "returns" error.`,
|
||||
},
|
||||
{
|
||||
Name: "ReturnsVoid",
|
||||
},
|
||||
{
|
||||
Name: "TakesContextReturnsError",
|
||||
IsError: true,
|
||||
IsContext: true,
|
||||
},
|
||||
{
|
||||
Name: "TakesContextReturnsVoid",
|
||||
IsError: false,
|
||||
IsContext: true,
|
||||
},
|
||||
}
|
||||
|
||||
// DefaultIsError
|
||||
if info.DefaultIsError != true {
|
||||
t.Fatalf("expected DefaultIsError to be true")
|
||||
}
|
||||
|
||||
// DefaultName
|
||||
if info.DefaultName != "ReturnsNilError" {
|
||||
t.Fatalf("expected DefaultName to be ReturnsNilError")
|
||||
}
|
||||
|
||||
for _, fn := range expected {
|
||||
found := false
|
||||
for _, infoFn := range info.Funcs {
|
||||
if reflect.DeepEqual(fn, infoFn) {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatalf("expected:\n%#v\n\nto be in:\n%#v", fn, info.Funcs)
|
||||
}
|
||||
}
|
||||
}
|
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
|
@ -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...)
|
||||
}
|
33
vendor/github.com/magefile/mage/parse/testdata/command.go
generated
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
// +build mage
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/magefile/mage/mg"
|
||||
)
|
||||
|
||||
// This should work as a default - even if it's in a different file
|
||||
var Default = ReturnsNilError
|
||||
|
||||
// this should not be a target because it returns a string
|
||||
func ReturnsString() string {
|
||||
fmt.Println("more stuff")
|
||||
return ""
|
||||
}
|
||||
|
||||
func ReturnsVoid() {
|
||||
mg.Deps(f)
|
||||
}
|
||||
|
||||
func f() {}
|
||||
|
||||
func TakesContextReturnsVoid(ctx context.Context) {
|
||||
|
||||
}
|
||||
|
||||
func TakesContextReturnsError(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
14
vendor/github.com/magefile/mage/parse/testdata/func.go
generated
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
// +build mage
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Synopsis for "returns" error.
|
||||
// And some more text.
|
||||
func ReturnsNilError() error {
|
||||
fmt.Println("stuff")
|
||||
return nil
|
||||
}
|
||||
|
||||
func nonexported() {}
|
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
|
||||
}
|
72
vendor/github.com/magefile/mage/sh/cmd_test.go
generated
vendored
Normal file
|
@ -0,0 +1,72 @@
|
|||
package sh
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestOutCmd(t *testing.T) {
|
||||
cmd := OutCmd(os.Args[0], "-printArgs", "foo", "bar")
|
||||
out, err := cmd("baz", "bat")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
expected := "[foo bar baz bat]"
|
||||
if out != expected {
|
||||
t.Fatalf("expected %q but got %q", expected, out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExitCode(t *testing.T) {
|
||||
ran, err := Exec(nil, nil, nil, os.Args[0], "-helper", "-exit", "99")
|
||||
if err == nil {
|
||||
t.Fatal("unexpected nil error from run")
|
||||
}
|
||||
if !ran {
|
||||
t.Errorf("ran returned as false, but should have been true")
|
||||
}
|
||||
code := ExitStatus(err)
|
||||
if code != 99 {
|
||||
t.Fatalf("expected exit status 99, but got %v", code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnv(t *testing.T) {
|
||||
env := "SOME_REALLY_LONG_MAGEFILE_SPECIFIC_THING"
|
||||
out := &bytes.Buffer{}
|
||||
ran, err := Exec(map[string]string{env: "foobar"}, out, nil, os.Args[0], "-printVar", env)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error from runner: %#v", err)
|
||||
}
|
||||
if !ran {
|
||||
t.Errorf("expected ran to be true but was false.")
|
||||
}
|
||||
if out.String() != "foobar\n" {
|
||||
t.Errorf("expected foobar, got %q", out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNotRun(t *testing.T) {
|
||||
ran, err := Exec(nil, nil, nil, "thiswontwork")
|
||||
if err == nil {
|
||||
t.Fatal("unexpected nil error")
|
||||
}
|
||||
if ran {
|
||||
t.Fatal("expected ran to be false but was true")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAutoExpand(t *testing.T) {
|
||||
if err := os.Setenv("MAGE_FOOBAR", "baz"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
s, err := Output("echo", "$MAGE_FOOBAR")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if s != "baz" {
|
||||
t.Fatalf(`Expected "baz" but got %q`, s)
|
||||
}
|
||||
|
||||
}
|
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)
|
||||
}
|
46
vendor/github.com/magefile/mage/sh/testmain_test.go
generated
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
package sh
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
helperCmd bool
|
||||
printArgs bool
|
||||
stderr string
|
||||
stdout string
|
||||
exitCode int
|
||||
printVar string
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.BoolVar(&helperCmd, "helper", false, "")
|
||||
flag.BoolVar(&printArgs, "printArgs", false, "")
|
||||
flag.StringVar(&stderr, "stderr", "", "")
|
||||
flag.StringVar(&stdout, "stdout", "", "")
|
||||
flag.IntVar(&exitCode, "exit", 0, "")
|
||||
flag.StringVar(&printVar, "printVar", "", "")
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
flag.Parse()
|
||||
|
||||
if printArgs {
|
||||
fmt.Println(flag.Args())
|
||||
return
|
||||
}
|
||||
if printVar != "" {
|
||||
fmt.Println(os.Getenv(printVar))
|
||||
return
|
||||
}
|
||||
|
||||
if helperCmd {
|
||||
fmt.Fprintln(os.Stderr, stderr)
|
||||
fmt.Fprintln(os.Stdout, stdout)
|
||||
os.Exit(exitCode)
|
||||
}
|
||||
os.Exit(m.Run())
|
||||
}
|
6
vendor/github.com/magefile/mage/site/archetypes/default.md
generated
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: "{{ replace .TranslationBaseName "-" " " | title }}"
|
||||
date: {{ .Date }}
|
||||
draft: true
|
||||
---
|
||||
|
34
vendor/github.com/magefile/mage/site/config.toml
generated
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
baseURL = "https://magefile.org"
|
||||
languageCode = "en-US"
|
||||
defaultContentLanguage = "en"
|
||||
|
||||
title = "Mage Documentation"
|
||||
theme = "learn"
|
||||
defaultContentLanguageInSubdir= true
|
||||
|
||||
[params]
|
||||
editURL = "https://github.com/magefile/mage/edit/master/site/content/"
|
||||
description = "Mage"
|
||||
author = "Nate Finch"
|
||||
showVisitedLinks = true
|
||||
|
||||
[outputs]
|
||||
home = [ "HTML", "RSS", "JSON"]
|
||||
|
||||
[Languages]
|
||||
[Languages.en]
|
||||
title = "Mage"
|
||||
weight = 1
|
||||
languageName = "English"
|
||||
|
||||
[[Languages.en.menu.shortcuts]]
|
||||
name = "<i class='fa fa-github'></i> Github repo"
|
||||
# identifier = "ds"
|
||||
url = "https://github.com/magefile/mage"
|
||||
weight = 10
|
||||
|
||||
[[Languages.en.menu.shortcuts]]
|
||||
name = "<i class='fa fa-twitter'></i> Twitter Account"
|
||||
# identifier = "ds"
|
||||
url = "https://twitter.com/MagefileDotOrg"
|
||||
weight = 20
|
74
vendor/github.com/magefile/mage/site/content/dependencies/_index.en.md
generated
vendored
Normal file
|
@ -0,0 +1,74 @@
|
|||
+++
|
||||
title = "Dependencies"
|
||||
weight = 30
|
||||
+++
|
||||
|
||||
Mage supports a makefile-style tree of dependencies using the helper library
|
||||
[github.com/magefile/mage/mg](https://godoc.org/github.com/magefile/mage/mg). To
|
||||
declare dependencies, pass any number of dependent functions of the following
|
||||
types:
|
||||
```
|
||||
func()
|
||||
func() error
|
||||
func(ctx context.Context)
|
||||
func(ctx context.Context) error
|
||||
```
|
||||
(they may be targets, but do not need to be and do not have to be exported) to
|
||||
`mg.Deps()`, and the Deps function will not return until all declared
|
||||
dependencies have been run (and any dependencies they have are run).
|
||||
Dependencies are guaranteed to run exactly once in a single execution of mage,
|
||||
so if two of your dependencies both depend on the same function, it is still
|
||||
guaranteed to be run only once, and both funcs that depend on it will not
|
||||
continue until it has been run.
|
||||
|
||||
## Parallelism
|
||||
|
||||
If run with `mg.Deps` or `mg.CtxDeps`, dependencies are run in their own
|
||||
goroutines, so they are parellelized as much as possible given the dependency
|
||||
tree ordering restrictions. If run with `mg.SerialDeps` or `mg.SerialCtxDeps`,
|
||||
the dependencies are run serially, though each dependency or sub-dependency will
|
||||
still only ever be run once.
|
||||
|
||||
## Contexts and Cancellation
|
||||
|
||||
Dependencies that have a context.Context argument will be passed a context,
|
||||
either a default context if passed into `mg.Deps` or `mg.SerialDeps`, or the one
|
||||
passed into `mg.CtxDeps` or `mg.SerialCtxDeps`. The default context, which is
|
||||
also passed into [targets](/targets) with a context argument, will be cancelled
|
||||
when and if the timeout specified on the command line is hit.
|
||||
|
||||
### Example Dependencies
|
||||
|
||||
```go
|
||||
func Build() {
|
||||
mg.Deps(f, g)
|
||||
fmt.Println("Build running")
|
||||
}
|
||||
|
||||
func f() {
|
||||
mg.Deps(h)
|
||||
fmt.Println("f running")
|
||||
}
|
||||
|
||||
func g() {
|
||||
mg.Deps(h)
|
||||
fmt.Println("g running")
|
||||
}
|
||||
|
||||
func h() {
|
||||
fmt.Println("h running")
|
||||
}
|
||||
```
|
||||
|
||||
Running `mage build` will produce the following output:
|
||||
|
||||
```
|
||||
h running
|
||||
g running
|
||||
f running
|
||||
Build running
|
||||
```
|
||||
|
||||
Note that since f and g do not depend on each other, and they're running in
|
||||
their own goroutines, their order is non-deterministic, other than they are
|
||||
guaranteed to run after h has finished, and before Build continues.
|
18
vendor/github.com/magefile/mage/site/content/filesources/_index.en.md
generated
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
+++
|
||||
title = "File Sources and Destinations"
|
||||
weight = 35
|
||||
+++
|
||||
|
||||
Mage supports make-like comparisons of file sources and file targets. Using the
|
||||
[target](https://godoc.org/github.com/magefile/mage/target) library, you can
|
||||
easily compare the last modified times of a target file or directory with the
|
||||
last modified time of the file or directories required to build that target.
|
||||
|
||||
`target.Path` compares the last modified time of a target file or directory with
|
||||
the last modified time of one or more files or directories. If any of the
|
||||
sources are newer than the destination, the function will return true. Note
|
||||
that Path does not recurse into directories. If you give it a directory, the
|
||||
only last modified time it'll check is that of the directory itself.
|
||||
|
||||
`target.Dir` is like `target.Path` except that it recursively checks files and
|
||||
directories under any directories specified, comparing timestamps.
|
23
vendor/github.com/magefile/mage/site/content/howitworks/_index.en.md
generated
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
+++
|
||||
title="How It Works"
|
||||
weight = 50
|
||||
+++
|
||||
|
||||
Mage scans the current directory for go files with the `mage` build tag (i.e.
|
||||
`// +build mage`), using the normal go build rules for following build
|
||||
constraints (aside from requiring the mage tag). It then parses those files to
|
||||
find the build targets, generates a main file for the command, and compiles a
|
||||
binary from those files. The magefiles are hashed so that if they remain
|
||||
unchanged, the same compiled binary will be reused next time, to avoid the
|
||||
generation overhead.
|
||||
|
||||
## Binary Cache
|
||||
|
||||
Compiled magefile binaries are stored in $HOME/.magefile. This location can be
|
||||
customized by setting the MAGEFILE_CACHE environment variable.
|
||||
|
||||
## Go Environment
|
||||
|
||||
Mage itself requires no dependencies to run. However, because it is compiling
|
||||
go code, you must have a valid go environment set up on your machine. Mage is
|
||||
compatible with any go 1.x environment.
|
72
vendor/github.com/magefile/mage/site/content/index.md
generated
vendored
Normal file
|
@ -0,0 +1,72 @@
|
|||
+++
|
||||
title = "Mage"
|
||||
+++
|
||||
|
||||
<p align="center"><img width=300 src="/images/gary.svg"/></p>
|
||||
|
||||
<p align="center">Mage is a make/rake-like build tool using Go.</p>
|
||||
|
||||
## 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). To
|
||||
install, just use `go get`:
|
||||
|
||||
`go get github.com/magefile/mage`
|
||||
|
||||
## Demo
|
||||
|
||||
{{< youtube GOqbD0lF-iA >}}
|
||||
|
||||
## Discussion
|
||||
|
||||
Join the `#mage` channel on [gophers slack](https://gophers.slack.com/messages/general/) for discussion of usage, development, etc.
|
||||
|
||||
|
||||
## Plugins
|
||||
|
||||
There are no plugins. You don't need plugins. It's just Go code. You can
|
||||
import whatever libraries you want. Every library in the go ecosystem is a mage
|
||||
plugin. Every tool you use with Go can be used with Magefiles.
|
||||
|
||||
## Usage
|
||||
```
|
||||
mage [options] [target]
|
||||
Options:
|
||||
-f force recreation of compiled magefile
|
||||
-h show this help
|
||||
-init
|
||||
create a starting template if no mage files exist
|
||||
-keep
|
||||
keep intermediate mage files around after running
|
||||
-l list mage targets in this directory
|
||||
-t string
|
||||
timeout in duration parsable format (e.g. 5m30s)
|
||||
-v show verbose output when running mage targets
|
||||
-version
|
||||
show version info for the mage binary
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
You may set MAGE_VERBOSE=1 to always enable verbose logging in your magefiles,
|
||||
without having to remember to pass -v every time.
|
||||
|
||||
## 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?
|
||||
|
||||
## Code
|
||||
|
||||
[https://github.com/magefile/mage](https://github.com/magefile/mage)
|
||||
|
||||
## Projects that build with Mage
|
||||
|
||||
[![Hugo](/images/hugo.png)](https://github.com/gohugoio/hugo) [![Gnorm](/images/gnorm.png)](https://github.com/gnormal/gnorm)
|
20
vendor/github.com/magefile/mage/site/content/libraries/_index.en.md
generated
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
+++
|
||||
title = "Helper Libraries"
|
||||
weight = 45
|
||||
+++
|
||||
|
||||
There are three helper libraries bundled with mage,
|
||||
[mg](https://godoc.org/github.com/magefile/mage/mg),
|
||||
[sh](https://godoc.org/github.com/magefile/mage/sh), and
|
||||
[target](https://godoc.org/github.com/magefile/mage/target)
|
||||
|
||||
Package `mg` contains mage-specific helpers, such as Deps for declaring
|
||||
dependent functions, and functions for returning errors with specific error
|
||||
codes that mage understands.
|
||||
|
||||
Package `sh` contains helpers for running shell-like commands with an API that's
|
||||
easier on the eyes and more helpful than os/exec, including things like
|
||||
understanding how to expand environment variables in command args.
|
||||
|
||||
Package `target` contains helpers for performing make-like timestamp cmoparing
|
||||
of files. It makes it easy to bail early if this target doesn't need to be run.
|
85
vendor/github.com/magefile/mage/site/content/magefiles/_index.en.md
generated
vendored
Normal file
|
@ -0,0 +1,85 @@
|
|||
+++
|
||||
title = "Magefiles"
|
||||
weight = 20
|
||||
+++
|
||||
|
||||
|
||||
A mage file is any regular go file marked with a build target of "mage" and in
|
||||
package main.
|
||||
|
||||
```go
|
||||
// +build mage
|
||||
|
||||
package main
|
||||
```
|
||||
|
||||
You can quickly create a template mage file with the `-init` option.
|
||||
|
||||
`mage -init`
|
||||
|
||||
You may have any number of magefiles in the same directory. Mage doesn't care
|
||||
what they're named aside from normal go filename rules. All they need is to
|
||||
have the mage build target. Handily, this also excludes them from your regular
|
||||
builds, so they can live side by side with your normal go files. Magefiles may
|
||||
use any of Go's usual build constraints, so you can include and exclude
|
||||
magefiles based on OS, arch, etc, whether in the filename or in the +build line.
|
||||
|
||||
```go
|
||||
// +build mage
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
|
||||
// Build target is any exported function with zero args with no return or an error return.
|
||||
// If a target has an error return and returns an non-nil error, mage will print
|
||||
// that error to stdout and return with an exit code of 1.
|
||||
func Install() error {
|
||||
|
||||
}
|
||||
|
||||
// The first sentence in the comment will be the short help text shown with mage -l.
|
||||
// The rest of the comment is long help text that will be shown with mage -h <target>
|
||||
func Target() {
|
||||
// by default, the log stdlib package will be set to discard output.
|
||||
// Running with mage -v will set the output to stdout.
|
||||
log.Printf("Hi!")
|
||||
}
|
||||
|
||||
// A var named Default indicates which target is the default.
|
||||
var Default = Install
|
||||
|
||||
|
||||
// Because build targets are case insensitive, you may not have two build targets
|
||||
// that lowercase to the same text. This would give you an error when you tried
|
||||
// to run the magefile:
|
||||
// func BUILD() {}
|
||||
|
||||
// Targets may have a context argument, in which case a default context is passed
|
||||
// to the target, which will be cancelled after a timeout if the -t flag is used.
|
||||
func Build(ctx context.Context) {
|
||||
mg.CtxDeps(ctx, Target)
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
$ mage -l
|
||||
Targets:
|
||||
install* Build target is any exported function with zero args with no return or an error return.
|
||||
target The first sentence in the comment will be the short help text shown with mage -l.
|
||||
|
||||
* default target
|
||||
```
|
||||
|
||||
```
|
||||
$ mage -h target
|
||||
mage target:
|
||||
|
||||
The first sentence in the comment will be the short help text shown with mage -l.
|
||||
The rest of the comment is long help text that will be shown with mage -h <target>
|
||||
```
|
50
vendor/github.com/magefile/mage/site/content/targets/_index.en.md
generated
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
+++
|
||||
title = "Targets"
|
||||
weight = 10
|
||||
+++
|
||||
A target is any exported function that is one of the following types:
|
||||
```
|
||||
func()
|
||||
func() error
|
||||
func(context.Context)
|
||||
func(context.Context) error
|
||||
```
|
||||
A target is effectively a subcommand of mage while running mage in
|
||||
this directory. i.e. you can run a target by running `mage <target>`
|
||||
|
||||
If the function has an error return, errors returned from the function will
|
||||
print to stdout and cause the magefile to exit with an exit code of 1. Any
|
||||
functions that do not fit this pattern are not considered targets by mage.
|
||||
|
||||
Comments on the target function will become documentation accessible by running
|
||||
`mage -l` which will list all the build targets in this directory with the first
|
||||
sentence from their docs, or `mage -h <target>` which will show the full comment
|
||||
from the docs on the function.
|
||||
|
||||
A target may be designated the default target, which is run when the user runs
|
||||
`mage` with no target specified. To denote the default, create a `var Default =
|
||||
<targetname>` If no default target is specified, running `mage` with no target
|
||||
will print the list of targets, like `mage -l`.
|
||||
|
||||
## Multiple Targets
|
||||
|
||||
Multiple targets can be specified as args to Mage, for example `mage foo bar
|
||||
baz`. Targets will be run serially, from left to right (so in thise case, foo,
|
||||
then once foo is done, bar, then once bar is done, baz). Dependencies run using
|
||||
mg.Deps will still only run once per mage execution, so if each of the targets
|
||||
depend on the same function, that function will only be run once for all
|
||||
targets. If any target panics or returns an error, no later targets will be run.
|
||||
|
||||
## Contexts and Cancellation
|
||||
|
||||
A default context is passed into any target with a context argument. This
|
||||
context will have a timeout if mage was run with -t, and thus will cancel the
|
||||
running targets and dependencies at that time. To pass this context to
|
||||
dependencies, use mg.CtxDeps(ctx, ...) to pass the context from the target to
|
||||
its dependencies (and pass the context to sub-dependencies). Dependencies run
|
||||
with mg.Deps will not get the starting context, and thus will not be cancelled
|
||||
when the timeout set with -t expires.
|
||||
|
||||
mg.CtxDeps will pass along whatever context you give it, so if you want to
|
||||
modify the original context, or pass in your own, that will work like you expect
|
||||
it to.
|
42
vendor/github.com/magefile/mage/site/content/zeroInstall/_index.en.md
generated
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
+++
|
||||
title = "Zero Install Option"
|
||||
weight = 40
|
||||
+++
|
||||
|
||||
|
||||
Don't want to depend on another binary in your environment? You can run mage
|
||||
directly out of your vendor directory (or GOPATH) with `go run`.
|
||||
|
||||
Just save a file like this (I'll call it `mage.go`, but it can be named
|
||||
anything. Note that the build tag is *not* `+build mage`. Mage will create its own main file, so we need this one to be excluded from when your magefiles are compiled.
|
||||
|
||||
Now you can `go run mage.go <target>` and it'll work just as if you ran `mage
|
||||
<target>`
|
||||
|
||||
```go
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"github.com/magefile/mage/mage"
|
||||
)
|
||||
|
||||
func main() { os.Exit(mage.Main()) }
|
||||
```
|
||||
|
||||
Note that because of the peculiarities of `go run`, if you run this way, go run
|
||||
will only ever exit with an error code of 0 or 1. If mage exits with error code
|
||||
99, for example, `go run` will print out `exit status 99" and then exit with
|
||||
error code 1. Why? Ask the go team. I've tried to get them to fix it, and
|
||||
they won't.
|
||||
|
||||
|
||||
## Use Mage as a library
|
||||
|
||||
All of mage's functionality is accessible as a compile-in library. Checkout
|
||||
[godoc.org/github.com/magefile/mage/mage](https://godoc.org/github.com/mage/mage)
|
||||
for full details.
|
||||
|
||||
Fair warning, the API of mage/mage may change, so be sure to use vendoring.
|
2
vendor/github.com/magefile/mage/site/layouts/partials/favicon.html
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
<link rel="shortcut icon" href="/images/favicon.ico" type="image/x-icon">
|
||||
<link rel="icon" href="/images/favicon.ico" type="image/x-icon">
|
2
vendor/github.com/magefile/mage/site/layouts/partials/logo.html
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
<h1>Mage</h1>
|
||||
<a id="logo" href="/"><img src="/images/gary.svg" width=300px /></a>
|
BIN
vendor/github.com/magefile/mage/site/static/images/favicon.ico
generated
vendored
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
vendor/github.com/magefile/mage/site/static/images/favicon.png
generated
vendored
Normal file
After Width: | Height: | Size: 306 KiB |
342
vendor/github.com/magefile/mage/site/static/images/gary.svg
generated
vendored
Normal file
|
@ -0,0 +1,342 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 21.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_3" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 1250 1250" style="enable-background:new 0 0 1250 1250;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#0D526D;stroke:#000000;stroke-miterlimit:10;}
|
||||
.st1{fill:#6ACFFB;stroke:#000000;stroke-miterlimit:10;}
|
||||
.st2{fill:url(#SVGID_1_);}
|
||||
.st3{fill:#54AECF;stroke:#000000;stroke-miterlimit:10;}
|
||||
.st4{fill:#FFFFFF;}
|
||||
.st5{fill:#D1B482;stroke:#000000;stroke-miterlimit:10;}
|
||||
.st6{fill:#FFEBE6;}
|
||||
.st7{fill:url(#SVGID_2_);}
|
||||
.st8{fill:url(#SVGID_3_);}
|
||||
.st9{fill:url(#SVGID_4_);}
|
||||
.st10{fill:#1A83B7;stroke:#000000;stroke-miterlimit:10;}
|
||||
.st11{fill:url(#SVGID_5_);}
|
||||
.st12{fill:url(#SVGID_6_);}
|
||||
.st13{fill:url(#SVGID_7_);}
|
||||
.st14{fill:url(#SVGID_8_);}
|
||||
.st15{fill:#916243;stroke:#000000;stroke-miterlimit:10;}
|
||||
.st16{fill:#7A4F37;}
|
||||
.st17{fill:none;stroke:#000000;stroke-miterlimit:10;}
|
||||
.st18{fill:url(#SVGID_9_);}
|
||||
.st19{fill:url(#SVGID_10_);}
|
||||
.st20{fill:url(#SVGID_11_);}
|
||||
.st21{fill:url(#SVGID_12_);stroke:#000000;stroke-miterlimit:10;}
|
||||
.st22{fill:url(#SVGID_13_);}
|
||||
.st23{fill:url(#SVGID_14_);}
|
||||
.st24{fill:url(#SVGID_15_);}
|
||||
.st25{fill:url(#SVGID_16_);stroke:#000000;stroke-miterlimit:10;}
|
||||
.st26{fill:url(#SVGID_17_);}
|
||||
.st27{fill:url(#SVGID_18_);}
|
||||
.st28{fill:url(#SVGID_19_);}
|
||||
.st29{stroke:#000000;stroke-miterlimit:10;}
|
||||
.st30{fill:#D1B482;}
|
||||
.st31{fill:url(#SVGID_20_);}
|
||||
.st32{fill:none;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
|
||||
.st33{fill:#D1B482;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
|
||||
.st34{fill:url(#SVGID_21_);}
|
||||
.st35{fill:url(#SVGID_22_);}
|
||||
</style>
|
||||
<g>
|
||||
<path class="st0" d="M430.6,655.5c0,0-73.3-2-88,0s-32.3,11-25.4,27s92.8,15,124.1,20s156.4,52,201.3,56c45,4,192.5-21,226.7-42
|
||||
s61.4-44.7,51.8-52c-26.4-20-155.4,10-155.4,10L430.6,655.5z"/>
|
||||
<g>
|
||||
<path class="st1" d="M538.5,447.5c0,0-117,96-138,234s9,349,9,349l439,12c0,0,38-320,36-389s-130-211-130-211c-18-8-137-28-160-21
|
||||
S538.5,447.5,538.5,447.5z"/>
|
||||
</g>
|
||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="502.8435" y1="722.8057" x2="498.6619" y2="660.6495">
|
||||
<stop offset="0.2872" style="stop-color:#6ACFFB"/>
|
||||
<stop offset="0.8764" style="stop-color:#54AECF"/>
|
||||
</linearGradient>
|
||||
<path class="st2" d="M461.9,705.5c22.5,9.3,48.6,8.8,71-0.7c24.5-10.5,44.8-33.4,46.9-60c-30.5,21.7-71.4,23.9-107.9,15.8
|
||||
c-9.2-2-63.1-17.3-54.3,4C425.1,682.9,444,698.1,461.9,705.5z"/>
|
||||
<path class="st3" d="M436.6,484.1c-8-3.2-16.4-5.4-24.9-6.6c-4.6-0.7-9.6-0.9-13.4,1.6c-4.9,3.2-6.3,9.9-4.8,15.6
|
||||
c1.4,5.6,5.1,10.4,8.7,14.9c5,6.4,10,12.8,15.1,19.2c2.1,2.7,4.5,5.6,7.9,6.4c3.5,0.8,7.1-0.8,10.3-2.4c5.6-2.8,11.3-5.7,16.9-8.5
|
||||
c10.8-5.4,23.2-13.5,22.5-25.6c-0.5-8.4-7.9-15.2-16-17.7s-16.8-1.6-25.2-0.7"/>
|
||||
<path class="st3" d="M898.2,529.1c8-3.2,16.4-5.4,24.9-6.6c4.6-0.7,9.6-0.9,13.4,1.6c4.9,3.2,6.3,9.9,4.8,15.6
|
||||
c-1.4,5.6-5.1,10.4-8.7,14.9c-5,6.4-10,12.8-15.1,19.2c-2.1,2.7-4.5,5.6-7.9,6.4c-3.5,0.8-7.1-0.8-10.3-2.4
|
||||
c-5.6-2.8-11.3-5.7-16.9-8.5c-10.8-5.4-23.2-13.5-22.5-25.6c0.5-8.4,7.9-15.2,16-17.7s16.8-1.6,25.2-0.7"/>
|
||||
<g>
|
||||
<path class="st4" d="M645.5,720.3c-9.3,0-16.8-6.1-19.5-16c-2.7-9.9,2.1-27.6,2.9-30.4h47.2c0.5,3.9,3.6,31.8-0.9,37.2
|
||||
c-4.5,5.4-12.1,6.6-22.8,8.3c-1,0.2-1.9,0.3-2.9,0.5C648.1,720.2,646.8,720.3,645.5,720.3C645.5,720.3,645.5,720.3,645.5,720.3z"
|
||||
/>
|
||||
<path d="M675.6,674.5c1.1,9.4,2.9,31.9-0.9,36.4c-4.3,5.2-11.9,6.5-22.5,8.2c-1,0.2-1.9,0.3-2.9,0.5c-1.3,0.2-2.6,0.3-3.8,0.3
|
||||
c-9.1,0-16.4-6-19-15.6c-2.6-9.4,1.8-26.1,2.8-29.7H675.6 M676.5,673.5h-48c0,0-6,20-3,31c2.7,9.7,10,16.3,20,16.3
|
||||
c1.3,0,2.6-0.1,4-0.3c12-2,21-3,26-9S676.5,673.5,676.5,673.5L676.5,673.5z"/>
|
||||
</g>
|
||||
<path class="st5" d="M510.5,410.9"/>
|
||||
<path class="st5" d="M808,458.6"/>
|
||||
<g>
|
||||
<path class="st6" d="M657.9,658.5c0,0-73.3,1-44,34.2c9.8,11.1,20.7-1,34.5,0c13.8,1,19.8,13.1,30.2,11.1s16.4-21.1,9.5-30.2
|
||||
C681.2,664.5,657.9,658.5,657.9,658.5z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st1" d="M516.5,1098.4c0,0-45,29.1-40.1,39.9c2.6,5.8,11.4,13.8,30.4,7.4c32.6-11,36.3-26,44.5-38.9
|
||||
c5.3-8.4-7.7-24.9-7.7-24.9L516.5,1098.4z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st1" d="M787.5,1108.5c0,0,50,24,40,40s-47,13-59,0c-9.7-10.5-26-37-26-37L787.5,1108.5z"/>
|
||||
</g>
|
||||
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="801.3585" y1="1163.4755" x2="774.4741" y2="1102.8389">
|
||||
<stop offset="0.2872" style="stop-color:#6ACFFB"/>
|
||||
<stop offset="0.8764" style="stop-color:#54AECF"/>
|
||||
</linearGradient>
|
||||
<path class="st7" d="M811.6,1128.5c-5.2,0.7-10.4,1.4-15.6,2c-5.9,0.8-11.9,1.6-17.2,4.4c-5.2,2.8-9.6,8.1-9.5,14
|
||||
c-7.8-8.5-10.8-16-17.3-23.1c17.1-3.4,34.7-4.1,52-2.3c5.5,0.6,10.5,1.8,14.8,5.4C816.5,1128,814,1128.2,811.6,1128.5z"/>
|
||||
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="493.4951" y1="1149.1807" x2="527.7737" y2="1102.3068">
|
||||
<stop offset="0.2872" style="stop-color:#6ACFFB"/>
|
||||
<stop offset="0.8764" style="stop-color:#54AECF"/>
|
||||
</linearGradient>
|
||||
<path class="st8" d="M495.7,1123.1c5.7,0.5,12.1,1.9,15,6.8c2.4,4.2,1.3,9.6-1,13.9c14.4-3.3,26.4-12.5,34.2-25.1
|
||||
c-18.7,0.4-36.4,0.8-55.1,1.3c-2,0-4.4,1-2.1,2.7C488.1,1123.7,493.8,1122.9,495.7,1123.1z"/>
|
||||
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="673.763" y1="685.9106" x2="860.0123" y2="685.9106">
|
||||
<stop offset="0.2872" style="stop-color:#6ACFFB"/>
|
||||
<stop offset="0.8764" style="stop-color:#54AECF"/>
|
||||
</linearGradient>
|
||||
<path class="st9" d="M699,759c-16,11,128.5-5.2,129.5-4.5c0.8,0.6,1.9,0.5,2.8,0.4c10.8-1,21.6-2.1,32.5-3.1
|
||||
c3.2-0.3,6.5-0.7,9.1-2.5c2.8-1.9,7.4-44.4,10.1-46.3c0.4-0.3,0-29,0-29c-1.4-4.5,3-5.8-0.2-9.2c-5.8-6-14.3-8.3-22.4-10.4
|
||||
c-34.8-9.3-68.7-22.1-100.9-38.2c-5.7-2.8-11.5-5.8-17.8-6.9c-26.2-4.6-12.9,41.4-6.7,54.7C743.3,682,724.6,741.4,699,759z"/>
|
||||
<g>
|
||||
<path class="st10" d="M362,741.9c2.7,3.2,5.2,0.9-2.7,17.2c-7.9,16.3,13.8,111,0.6,164.9c-3.2,13.1-7.4,26.5-16.1,36.7
|
||||
c-5.8,6.8-13.5,12.1-18.2,19.7c-4.6,7.4-6.1,16.4-10.3,24.1c-4.8,8.8-12.9,15.3-20.9,21.3c-34.1,25.6-110.7,57-109.5,65.3
|
||||
c21.8,26.3,84.4,12.2,126.6,18.3c31.7,4.6,63.3,9.1,95.3,11c87.6,5.2,175.5-10,262.9-3.2c43.2,3.4,86.3,12.1,129.6,9.9
|
||||
c36.3-1.9,71.8-11.4,106.9-20.9c39.3-10.6,78.6-21.2,117.8-31.8c7-1.9,15.4-5.3,16.2-12.7c0.8-7.6-7.2-12.8-14.2-15.3
|
||||
c-20.6-7.5-43.2-9.1-62.7-19.2c-6.1-3.2-12.7-8.9-11.5-15.8c0.6-3.6,3.2-6.5,4.6-9.8c4.6-10.9-4.1-22.5-11.6-31.6
|
||||
c-41.2-49.9-61.9-117.1-55.9-182.2c1.3-14,4-28.6,12.6-39.6c7.6-27.1,21.7-60.7,21.7-81.7c-111.4,134.5-350.2,41-524.1,30
|
||||
c-81.1-5.1-83.1-22-83.1-22C303.7,693.9,351.3,729.3,362,741.9z"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="598" y1="894.7486" x2="921.0349" y2="894.7486">
|
||||
<stop offset="0" style="stop-color:#1A83B7"/>
|
||||
<stop offset="0.8522" style="stop-color:#0E5E77"/>
|
||||
</linearGradient>
|
||||
<path class="st11" d="M1026.2,1046.4c-20.6-7.5-43.2-9.1-62.7-19.2c-6.1-3.2-12.7-8.9-11.5-15.8c0.6-3.6,3.2-6.5,4.6-9.8
|
||||
c4.6-10.9-4.1-22.5-11.6-31.6c-41.2-49.9-61.9-117.1-55.9-182.2c1.3-14,4-28.6,12.6-39.6c7.3-25.8,20.3-57.3,21.6-78.4
|
||||
c-4.2,3.7-8.4,7.3-12.8,10.8c-29,28.4-65,44.3-105.3,51.9c-16.3,4-33,6.4-49.7,8.3C745,742,733.1,744,723,745
|
||||
c-10.2,1-21,4-17.9,10.1c5.1,2.6,10.1,5.2,15.2,7.8c1.5,0.7,3,1.6,3.6,3.2c1.2,3.5-3.4,5.9-7,6.7c-37.2,7.7-75.2,11.8-113.3,12.1
|
||||
c1.9,8.5,12.3,11.6,20.9,13.1c25.2,4.4,50.4,8.9,75.7,13.3c5.2,0.9,11.8,3.6,11.2,8.8c-0.3,2.4-2.2,4.3-3.9,5.9
|
||||
c-13.6,12.3-29.1,22.4-45.9,29.9c8.8,7.4,9.3,20.4,10.3,31.8c3,31.6,15.6,62.3,35.8,86.8c1.8,2.2,3.8,4.5,4.5,7.3
|
||||
c1.1,4.6-1.4,9.2-3.6,13.5c-3.6,6.9-6.6,14.2-8.8,21.6c-0.7,2.5-1.4,5.1-0.7,7.5c1.6,5.4,8.6,7,14.1,6c5.5-1,10.9-3.6,16.4-3
|
||||
c3.1,7.3-2.4,15.2-7.8,21c-9,9.5-19,18.2-26.4,29c-7.4,10.8-16.6,27.9-13.3,40.6c0.9,0.2,1.8,0.4,2.7,0.7
|
||||
c24.7,2.5,49.4,6.2,74.1,7.9c3.8,0.2,7.6,0.3,11.3,0.5c4.6,0.2,9.1,0.4,13.7,0.5c5.2,0,10.4-0.1,15.7-0.4
|
||||
c36.3-1.9,71.8-11.4,106.9-20.9c39.3-10.6,78.6-21.2,117.8-31.8c7-1.9,15.4-5.3,16.2-12.7
|
||||
C1041.1,1054.2,1033.2,1049,1026.2,1046.4z"/>
|
||||
</g>
|
||||
</g>
|
||||
<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="609.7143" y1="988.8874" x2="669.9747" y2="898.996">
|
||||
<stop offset="0" style="stop-color:#1A83B7;stop-opacity:0"/>
|
||||
<stop offset="0.6251" style="stop-color:#0E5E77"/>
|
||||
</linearGradient>
|
||||
<path class="st12" d="M639.6,939.4c-10.6-9.1-19.2-20.2-28.7-30.5c-5.2-5.7-11-11.3-18.3-13.9s-16.5-1.2-21,5c-0.5,0.7-1,1.6-1,2.5
|
||||
c-0.1,1.4,0.9,2.6,1.8,3.7c16.4,19.2,32.7,38.4,49.1,57.6c3.3,3.9,6.6,7.7,10.3,11.2c4.3,3.9,9.1,7.2,13.4,11.1
|
||||
c6.8,6.2,12.2,14,16.2,22.3c5.1,10.6,8.1,22.2,8.7,34c3.3-0.8,4.4-5,4.7-8.4c2.2-21.9,5.2-45.5,3.4-67.5c-1.1-13-4.4-9.1-16.1-13.3
|
||||
C653.8,950.2,646.2,945.1,639.6,939.4z"/>
|
||||
<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="425.4122" y1="815.0155" x2="536.7072" y2="733.6134">
|
||||
<stop offset="0" style="stop-color:#1A83B7;stop-opacity:0"/>
|
||||
<stop offset="0.6251" style="stop-color:#0E5E77"/>
|
||||
</linearGradient>
|
||||
<path class="st13" d="M419.4,741.2c14.3,27.4,34.9,50.9,56.8,72.7c9.3,9.3,34.8,40.1,35.8,43.1c8.4,3.6-1.2-2.5,7.2,1
|
||||
c3.9,1.7,8,3.3,12.2,3c4.2-0.4,8.6-3.5,8.7-7.7c0.1-3.7-2.8-6.7-5.4-9.3c-31.9-30.8-61.3-64.2-87.6-99.9
|
||||
c-8.9-12.1-20.9-31.6-35.9-36.9c-10.9-3.8-10.4-0.6-6.2,7.6C409.4,723.7,414.8,732.3,419.4,741.2z"/>
|
||||
<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="455.0909" y1="1016.1805" x2="440.2752" y2="1193.2762">
|
||||
<stop offset="0" style="stop-color:#1A83B7;stop-opacity:0"/>
|
||||
<stop offset="0.6251" style="stop-color:#0E5E77"/>
|
||||
</linearGradient>
|
||||
<path class="st14" d="M709,1103c-17.3,1.2-87-1.9-93.6-1.3c-17.8,1.6-35.1-4.7-52.3-10c1.8-3.3,0.5-7.8-2.3-10.5
|
||||
c-2.9-2.8-6.9-4.1-10.9-5.1c-14.1-3.5-28.7-4.3-42.6-8.7c-6.6-2.1-13-5-19.3-7.9c-19.2-8.7-38.6-17.5-55.9-29.6
|
||||
c-4.1-2.9-8.1-5.9-12.3-8.6c-2.5,6.3,1.2,13.1,4.7,18.8c4.4,7.1,8.7,14.2,13.1,21.3c1.1,1.7,2.1,3.6,1.9,5.6c0,0.4,1.1,1,3.3,1.8
|
||||
c-0.1,0-0.2,0-0.2,0c-6.1-1-12.2-1.9-18.4-2c-6.8-0.1-13.6,0.9-20.4,1.3c-14.5,0.8-28-2.1-42.2-3.4c-15.9-1.5-30.3,4.7-45.6,7.9
|
||||
c-22.7,4.7-46.6-0.1-69.1,5.7c4.3,1.1,5,7.6,2,10.9s-7.7,4.2-12.1,4.7c-16.7,1.9-33.7,1.5-50.2-1.3c24.3,18.8,58.2,16.5,88.9,14.5
|
||||
c26.5-1.7,45.5,3,71.6,7.9c11.1,2.1,34.9,3.3,46,5c10.8,1.7,21.1,0.6,32,1c22.6,0.9,40.7-0.3,63.3-1.3c19.2-0.9,45.4-0.8,64.7-1.7
|
||||
c21.1-1,35.3-2.9,56.5-2.3c30.3,0.8,58.5-0.7,88.5,3.3C708,1122,711.5,1102.8,709,1103z"/>
|
||||
<path class="st15" d="M167.3,514.3c-4.8,27.7,4.2,58.7,26.4,75.9c24.4,18.8,57.9,18.2,88.2,24.1c30.3,5.9,63.8,26.6,62.1,57.4
|
||||
c-0.2,4.1-1.1,8.4,0.6,12.2c2.8,6.4,11,7.9,17.8,9.9c20.7,6.1,35.3,23.9,49.2,40.3c25.1,29.4,52.2,57,79.7,84.1
|
||||
c66.1,65.1,134.5,127.7,205.1,187.8c22,18.7,44.3,37.2,66.5,55.7c47.1,39.1,94.1,78.3,141.2,117.4c0.8-12.5-8.1-23.2-16.7-32.3
|
||||
c-55.1-58.7-119.2-108.1-179.5-161.5c-69.4-61.6-133.8-128.8-194.2-199.1c-36.9-43-72.9-87.6-117.9-122
|
||||
c-16-12.2-27.7-48.8-41.4-63.6c-11.5-12.4-25.6-1.4-34.2-15.9c-5.7-9.6-11-22.9-3-30.7c5.3-5.2,14.8-5.4,18.7-11.8
|
||||
c3.3-5.6,0.4-12.7-2.5-18.5c-7.4-14.5-14.7-29-22.1-43.5c-7.1-14.1-14.6-28.5-26.7-38.6C233.1,398.5,175.7,465.6,167.3,514.3z"/>
|
||||
<path class="st16" d="M696.4,1005.9c22,18.7,44.3,37.2,66.5,55.7c47.1,39.1,94.1,78.3,141.2,117.4c0.8-12.5-8.1-23.2-16.7-32.3
|
||||
c-55.1-58.7-119.2-108.1-179.5-161.5C638.6,923.6,625.8,945.8,696.4,1005.9z"/>
|
||||
<path class="st16" d="M613,895c-0.9,0-1,4.6-1.6,5.3c-3.3,3.7-7.2,7-11.7,9c-2,0.9-5.7,4.6-7.7,3.7c-1.4-0.7-7.6-6.5-10.5-10.7
|
||||
c-0.5-0.7-0.9-1.5-0.8-2.3c0.1-0.8,0.9-1.4,1.5-1.9c4.6-3.2,16.2-11.2,21.7-12.2C604,886,613.2,895,613,895z"/>
|
||||
<path class="st16" d="M653.9,969.1c6.1,3.9,11.5,8.8,16.1,14.4c0-6.2-0.1-12.5-0.1-18.7c-5,2.6-10.7,3.8-16.3,3.5"/>
|
||||
<path class="st17" d="M435.7,790.6c0.8,16.6,6.2,33,15.5,46.8"/>
|
||||
<path class="st17" d="M649.5,686c0.7,7.5,1.4,15.1,2,22.6"/>
|
||||
<g>
|
||||
<g>
|
||||
<linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="613.3805" y1="675.2397" x2="697.8409" y2="699.4741">
|
||||
<stop offset="0.2872" style="stop-color:#FFEBE6"/>
|
||||
<stop offset="0.8764" style="stop-color:#E5D2CF"/>
|
||||
</linearGradient>
|
||||
<path class="st18" d="M673.4,663.9c-0.5,0.1-1,0.1-1.5,0.2c-2,0.4-4.2,1.1-5.5,2.7c-3,3.7-0.1,9.5-2.2,13.8
|
||||
c-1.8,3.6-6.3,4.6-10.3,4.6c-7.7-0.1-15.7-2.8-22.9-0.1c-2.3,0.9-4.4,2.3-6.6,3.3c-4.3,2-8.6,2.3-12.7,1.6
|
||||
c0.7,0.9,1.4,1.8,2.3,2.8c9.8,11.1,20.7-1,34.5,0c13.8,1,19.8,13.1,30.2,11.1c10.3-2,16.4-21.1,9.5-30.2
|
||||
C685.1,669.7,679.2,666.4,673.4,663.9z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path d="M657.8,659.5c1.9,0.5,23.1,6.4,29.5,14.7c3.2,4.3,3.7,11.4,1.1,18.3c-2.2,5.7-5.9,9.5-9.9,10.3c-0.7,0.1-1.4,0.2-2.1,0.2
|
||||
c-4,0-7.4-2.2-11.3-4.7c-4.5-2.9-9.5-6.1-16.5-6.6c-0.6,0-1.2-0.1-1.7-0.1c-4.8,0-9.1,1.3-13.2,2.6c-3.5,1.1-6.8,2.1-9.9,2.1
|
||||
c-3.5,0-6.4-1.4-9-4.4c-6-6.8-7.9-12.6-5.9-17.2C615.1,660.7,655.1,659.6,657.8,659.5 M657.9,658.5c0,0-73.3,1-44,34.2
|
||||
c3.1,3.5,6.3,4.7,9.7,4.7c6.8,0,14.4-4.8,23.1-4.8c0.6,0,1.1,0,1.7,0.1c12.7,0.9,18.9,11.3,27.9,11.3c0.7,0,1.5-0.1,2.3-0.2
|
||||
c10.3-2,16.4-21.1,9.5-30.2C681.2,664.5,657.9,658.5,657.9,658.5L657.9,658.5z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st1" d="M605.3,862.7c2,3.4,2.3,7.3,2.1,11.1c-0.5,9.2-4,18.8-12.8,24.7c-8.3,5.6-19.7,7-30.4,8.2
|
||||
c-3.7,0.4-8.1,0.6-10.4-1.7c-1.6-1.6-1.5-3.8-1.4-5.9c0.9-12.5,1.7-29.6,16.3-37.1C578.1,857.1,599.5,853,605.3,862.7z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st1" d="M638.4,929.9c-3.2,1.4-6.7,3.1-7.7,6.4c-0.7,2.2-0.2,4.5,0.4,6.7c2.6,10.4,6.9,22.6,17.3,25.2
|
||||
c4.8,1.2,9.8-0.1,14.5-1.3c10-2.7,21.2-6.2,25.8-15.6c1.6-3.2,2.1-6.8,2.1-10.4C690.7,903.3,657.4,921.6,638.4,929.9z"/>
|
||||
</g>
|
||||
<linearGradient id="SVGID_10_" gradientUnits="userSpaceOnUse" x1="644.2117" y1="940.9792" x2="666.1635" y2="967.2874">
|
||||
<stop offset="0.2872" style="stop-color:#6ACFFB"/>
|
||||
<stop offset="0.8764" style="stop-color:#54AECF"/>
|
||||
</linearGradient>
|
||||
<path class="st19" d="M652.4,950c5.2-2,9.3-6.4,11.7-11.4c2.3,7.8,4.1,15.7,5.3,23.7c0.1,0.8,0.2,1.8-0.3,2.4
|
||||
c-0.4,0.4-1,0.6-1.6,0.8c-5,1.2-10.1,2-15.2,2.2c-1.4,0.1-2.9,0.1-4.3-0.3c-1.7-0.4-4.2-1.4-5.5-2.5c-4.5-3.9-7.5-12.9-7.3-13
|
||||
c1.4-1.1,6.6-0.4,8.2-0.4C646.4,951.3,649.5,951.1,652.4,950z"/>
|
||||
<linearGradient id="SVGID_11_" gradientUnits="userSpaceOnUse" x1="591.1284" y1="871.0673" x2="594.7662" y2="898.6528">
|
||||
<stop offset="0.2872" style="stop-color:#6ACFFB"/>
|
||||
<stop offset="0.8764" style="stop-color:#54AECF"/>
|
||||
</linearGradient>
|
||||
<path class="st20" d="M604.9,863.7c1.8,0.9,1.9,3.4,1.8,5.4c-0.1,2.6-0.3,5.1-0.4,7.7c-0.1,2.3-1.3,4.7-1.9,7
|
||||
c-1.4,5.6-4.4,10.2-9.2,13.5s-10.2,5.2-15.7,6.9c0-3-0.1-6-0.1-8.9c0-1.8-0.9-6.3-0.1-7.9c1.2-2.2,8.2-3.3,10.7-4.8
|
||||
c3.6-2.1,6.8-4.9,9.4-8.1C600,873.6,606,864.3,604.9,863.7z"/>
|
||||
<path class="st10" d="M399.4,803.5c2.2,11.5,14.4,17.9,25.2,22.5c46.4,19.9,99.8,38.4,146,18c8.4,4.4,9.4,15.8,9.2,25.3
|
||||
c-0.9,59.5-1.7,119.1-2.6,178.6c-0.2,15.2-0.5,30.6-5,45c-12,2-27.3-5.6-37.9-11.6c-18.8-10.7-98.8-38.9-113.8-59.9"/>
|
||||
<linearGradient id="SVGID_12_" gradientUnits="userSpaceOnUse" x1="673.9017" y1="963.3705" x2="853.5" y2="963.3705">
|
||||
<stop offset="0" style="stop-color:#1A83B7"/>
|
||||
<stop offset="1" style="stop-color:#0E5E77"/>
|
||||
</linearGradient>
|
||||
<path class="st21" d="M824.4,818c-39.5,43.5-92.6,74.6-149.8,87.9c-5.2,1.2-11,2.7-13.5,7.4c-2.5,4.7-0.5,10.4,1.2,15.4
|
||||
c18.5,54.5-2.5,114.7,6.2,171.5c0.4,2.9,1.2,6.3,3.8,7.7c1.9,1.1,4.4,0.8,6.6,0.5c36.2-5.2,80.8-16.1,106.7-42c12-12,49.2-43,54-56
|
||||
"/>
|
||||
<path class="st17" d="M785.5,853.5c6.9-9,9.3-21.5,8-32.8"/>
|
||||
<linearGradient id="SVGID_13_" gradientUnits="userSpaceOnUse" x1="743.4565" y1="942.679" x2="942.2493" y2="942.679">
|
||||
<stop offset="0" style="stop-color:#1A83B7"/>
|
||||
<stop offset="0.6263" style="stop-color:#0E5E77;stop-opacity:0"/>
|
||||
</linearGradient>
|
||||
<path class="st22" d="M693.1,915.8c-3.4,0.7-7.1,1.5-9.5,3.9c-3.3,3.4-3.2,8.8-2.9,13.6c1.1,15.7,2.3,31.4,3.5,47.1
|
||||
c2.8-2.7,5.6-5.5,8.3-8.2c-1.6,11.8-3.2,23.5-4.8,35.3c-1.5,11.4-2.1,25.3,7.3,31.9c6.6,4.7,16,3.5,23-0.6c7-4.1,12.1-10.7,17-17.2
|
||||
c9-11.8,18-23.6,27-35.5c2.6,22.6-12.2,43.8-29.5,58.7c-13.5,11.7-29.1,21.3-39.5,35.9c-2.6,3.6-4.9,7.7-8.7,10
|
||||
c-3.8,2.4-9.6,2.3-11.9-1.5c-0.9-1.5-1.1-3.2-1.3-4.9c-2.5-20.8-2.8-41.9-1-62.8c1.3-15.5,3.8-31.1,2.4-46.6
|
||||
c-1.7-18.4-8.8-36.1-10-54.6c-0.1-2.2-0.2-4.6,1-6.5c1.2-1.9,3.4-3,5.5-3.8c22-8.1,43-14,63.9-23c43.7-18.8,82-50.7,109.6-89.4
|
||||
c-0.7,4.1-1.4,8.3-2.1,12.4c7.9-4.5,14.9-10.3,20.9-17.1c-4.1,4.8-4.4,15.3-9.2,21.1c-5.9,7.3-13.2,9.6-20.7,14.5
|
||||
c-13,8.4-23.8,21.7-35.9,31.6C765.3,884.9,731.8,907.5,693.1,915.8z"/>
|
||||
<linearGradient id="SVGID_14_" gradientUnits="userSpaceOnUse" x1="251.4727" y1="1022.9849" x2="403.3306" y2="1022.9849">
|
||||
<stop offset="0.2367" style="stop-color:#0E5E77"/>
|
||||
<stop offset="1" style="stop-color:#1A83B7;stop-opacity:0"/>
|
||||
</linearGradient>
|
||||
<path class="st23" d="M320.9,1009c2.6,8.2,10.6,13.7,18.9,15.7c8.3,2,17.1,1.1,25.6,0.2c-4.1,3.2-8.1,6.4-12.2,9.7
|
||||
c7.7,7.7,19.2,9.9,30,10.8c10.8,0.9,22.1,1.1,31.8,5.9c-18,3.7-36.8,3.6-54.8-0.4c-9.6-2.1-19.1-5.4-28.9-5.1
|
||||
c-6.2,0.2-12.2,1.9-18.3,2.9c-19.7,3.4-40.1,0.5-59.6,4.8c6-8.5,21.5-13.5,34.5-22.5c18.2-12.6,29-21,32.3-39
|
||||
C322.2,997,319.1,1003.3,320.9,1009z"/>
|
||||
<linearGradient id="SVGID_15_" gradientUnits="userSpaceOnUse" x1="274.2131" y1="603.0543" x2="278.36" y2="548.9128">
|
||||
<stop offset="0.2872" style="stop-color:#916243"/>
|
||||
<stop offset="0.8764" style="stop-color:#7A4F37"/>
|
||||
</linearGradient>
|
||||
<path class="st24" d="M227.9,536.5c1.5,15,10.4,29.2,23.2,37.1c2.2,1.4,4.5,2.5,7,3.1c2.5,0.5,5.2,0.3,7.7,0.2
|
||||
c15-1.1,31.8-1.6,43,8.4c2.6,2.3,4.8,5.2,7.8,7s7.2,2.4,9.8,0.1c-6-6.1-11.9-13-13.6-21.4s1.9-18.5,10.1-21.3
|
||||
c-8.9,3.1-17.8,6.2-26.7,9.3c-11,3.8-22.4,7.7-34.1,7.4c-11.7-0.4-23.9-6-28.9-16.5C231.2,545.5,229.5,540.8,227.9,536.5z"/>
|
||||
<path class="st17" d="M334.5,544.5c-11.5,7.4-38.8,15.5-52,19c-8.7,2.3-17.9,3.7-26.8,2.2c-8.9-1.5-17.5-6.2-22.3-13.8
|
||||
c-3.3-5.3-4.5-11.6-5.6-17.7c-2.4-12.7-4.8-25.4-7.2-38.1c-0.3-1.4-0.5-2.9,0.1-4.1c0.5-1,1.5-1.6,2.4-2.2
|
||||
c10.8-6.8,23.1-14,35.6-11.2c9.6,2.1,16.9,9.6,23.6,16.7c3.8,4,7.5,8,11.3,12c2.4,2.5,5,5.7,4.3,9.1c-0.4,2-1.8,3.6-3.3,4.9
|
||||
c-5,4.3-11.9,6.7-18.4,5.3c-6.5-1.3-12.2-6.6-13.2-13.2"/>
|
||||
|
||||
<radialGradient id="SVGID_16_" cx="644" cy="654" r="22.463" gradientTransform="matrix(1 0 0 0.6232 0 246.3962)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" style="stop-color:#666666"/>
|
||||
<stop offset="1" style="stop-color:#000000"/>
|
||||
</radialGradient>
|
||||
<path class="st25" d="M682.3,662.1c-1.1,8.2-14.4,13.3-29.7,11.3c-15.3-2-26.9-10.3-25.8-18.5c1.1-8.2,14.4-13.3,29.7-11.3
|
||||
C671.8,645.6,683.3,653.9,682.3,662.1z"/>
|
||||
<linearGradient id="SVGID_17_" gradientUnits="userSpaceOnUse" x1="661.8317" y1="633.6916" x2="662.598" y2="468.1831">
|
||||
<stop offset="0.2872" style="stop-color:#6ACFFB"/>
|
||||
<stop offset="0.8764" style="stop-color:#54AECF"/>
|
||||
</linearGradient>
|
||||
<path class="st26" d="M752.8,569.7c-2.3-3.4-4.8-6.9-7.7-9.8c19.2,0.9,38.5,1.4,57.7,1.3c12.2,0,24.7-0.2,36.3,3.8
|
||||
c0.3-7.7-3.8-15.1-9.4-20.4c-5.6-5.3-12.7-8.8-19.8-11.9c-20.4-8.9-41.9-15.1-63.5-20.3c-82-20-167.7-27.8-251.1-14.9
|
||||
c-1.7,0.3-3.5,0.6-4.9,1.7c-4,3.1-6.4,10-4.3,13.1c2.7,4.1,13.2,7.5,17.7,9.6c12.4,5.9,25.3,10.5,38.5,14.1
|
||||
c26.5,7.3,53.9,10.9,81.2,13.9c21.7,2.4,43.4,4.6,65.1,6.4c0,0,0,0,0,0c3.8,3.5,4.4,9.2,4.6,14.4c1.4,24.9,2.4,51,14.4,72.9
|
||||
C717.7,661.6,778.5,607.7,752.8,569.7z"/>
|
||||
<g>
|
||||
<radialGradient id="SVGID_18_" cx="498.5" cy="596.5" r="103.0109" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" style="stop-color:#FFFFFF"/>
|
||||
<stop offset="0.4455" style="stop-color:#FDFDFD"/>
|
||||
<stop offset="1" style="stop-color:#E6E6E6"/>
|
||||
</radialGradient>
|
||||
<path class="st27" d="M498.5,698C440.9,698,394,652.5,394,596.5S440.9,495,498.5,495S603,540.5,603,596.5S556.1,698,498.5,698z"/>
|
||||
<g>
|
||||
<path d="M498.5,495.5c57.3,0,104,45.3,104,101s-46.7,101-104,101s-104-45.3-104-101S441.2,495.5,498.5,495.5 M498.5,494.5
|
||||
c-58,0-105,45.7-105,102c0,56.3,47,102,105,102s105-45.7,105-102C603.5,540.2,556.5,494.5,498.5,494.5L498.5,494.5z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<radialGradient id="SVGID_19_" cx="818" cy="599.8713" r="98.5748" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" style="stop-color:#FFFFFF"/>
|
||||
<stop offset="0.4455" style="stop-color:#FDFDFD"/>
|
||||
<stop offset="1" style="stop-color:#E6E6E6"/>
|
||||
</radialGradient>
|
||||
<path class="st28" d="M818,697c-55.1,0-100-43.6-100-97.1c0-53.6,44.9-97.1,100-97.1s100,43.6,100,97.1
|
||||
C918,653.4,873.1,697,818,697z"/>
|
||||
<g>
|
||||
<path d="M818,503.2c54.9,0,99.5,43.3,99.5,96.6s-44.6,96.6-99.5,96.6s-99.5-43.3-99.5-96.6S763.1,503.2,818,503.2 M818,502.2
|
||||
c-55.5,0-100.5,43.7-100.5,97.6c0,53.9,45,97.6,100.5,97.6s100.5-43.7,100.5-97.6C918.5,546,873.5,502.2,818,502.2L818,502.2z"/>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<ellipse transform="matrix(8.600707e-02 -0.9963 0.9963 8.600707e-02 -114.255 1019.4568)" class="st29" cx="498.5" cy="572" rx="20.5" ry="14"/>
|
||||
|
||||
<ellipse transform="matrix(0.9956 -9.351500e-02 9.351500e-02 0.9956 -51.6696 79.3657)" class="st29" cx="821" cy="591" rx="13.5" ry="20.5"/>
|
||||
<g>
|
||||
<path class="st30" d="M631.6,538.3c101.9,12.7,346.1,10.9,374-10c27.9-20.8-186.5-133.9-314.4-147.5s-359.1,48.6-375.9,57
|
||||
C268.2,461.4,529.7,525.7,631.6,538.3z"/>
|
||||
</g>
|
||||
<g>
|
||||
<linearGradient id="SVGID_20_" gradientUnits="userSpaceOnUse" x1="652.8838" y1="501.3271" x2="579.8838" y2="738.3271">
|
||||
<stop offset="0" style="stop-color:#D1B482"/>
|
||||
<stop offset="0.6251" style="stop-color:#A68B65"/>
|
||||
</linearGradient>
|
||||
<path class="st31" d="M631.6,538.3c101.9,12.7,346.1,10.9,374-10C736,566,367,502,315.3,437.9
|
||||
C268.2,461.4,529.7,525.7,631.6,538.3z"/>
|
||||
</g>
|
||||
<path class="st32" d="M522.2,402.7c-1.5,7.8,5.2,14.6,11.7,19.1c13.5,9.4,29,16,45.2,19.1"/>
|
||||
<path class="st33" d="M521.6,404.3c45.3-92.8,92.7-184.5,142.2-275.1c6.9-12.7,14.3-25.8,25.9-34.3c9.2-6.7,20.3-10.1,31.3-12.9
|
||||
c15.8-4.1,31.8-7.3,48-9.6c9.8-1.4,20.2-2.4,29,2c6.9,3.4,11.9,9.8,16.5,16c13.2,17.8,25.4,36.3,36.5,55.5
|
||||
c8.9,15.4,17.9,32.2,33.6,40.7c15.7,8.5,40,3.1,43.9-14.3c0.5,21.6-10,43.2-27.2,56.3c-17.2,13.1-40.9,17.3-61.6,10.9
|
||||
c-4.8-1.5-10.2-3.4-14.6-0.9c-4,2.3-5.3,7.4-6.2,11.9c-12.3,65-9.7,132.7,7.5,196.6"/>
|
||||
<g>
|
||||
<linearGradient id="SVGID_21_" gradientUnits="userSpaceOnUse" x1="779.9537" y1="84.214" x2="1232.931" y2="270.2047">
|
||||
<stop offset="0" style="stop-color:#D1B482"/>
|
||||
<stop offset="0.6251" style="stop-color:#A68B65"/>
|
||||
</linearGradient>
|
||||
<path class="st34" d="M799.2,93.1c-0.1-0.7-0.2-1.3-0.2-2C799,91.7,799.1,92.4,799.2,93.1z"/>
|
||||
<linearGradient id="SVGID_22_" gradientUnits="userSpaceOnUse" x1="687.6368" y1="309.0503" x2="1140.6141" y2="495.041">
|
||||
<stop offset="0" style="stop-color:#D1B482"/>
|
||||
<stop offset="0.6251" style="stop-color:#A68B65"/>
|
||||
</linearGradient>
|
||||
<path class="st35" d="M819,414.2c-10.1-53.9-10.2-109.7,0-163.6c0.9-4.5,2.2-9.6,6.2-11.9c4.4-2.5,9.8-0.5,14.6,0.9
|
||||
c9.2,2.8,18.9,3.5,28.5,2.3c-2.3-7.8-5-15.6-7.6-23.3c-7.3-21.4-12.8-40.6-23.9-60.4c-6.5-11.6-13-23.1-19.5-34.7
|
||||
c-3.9-6.9-16.2-21.7-18-30.5c2.7,23.1,5.3,46.3,3.1,69.4c-2.3,23.8-10.2,47.7-26.4,65.3c-7.3,8-17,17.5-13.2,27.6
|
||||
c1.5,3.9,4.8,6.8,7.3,10.1c15.8,20.8-1.5,53.1,10.7,76.2c3.2,6,8.3,12.2,6.3,18.6c-1.7,5.1-7.3,7.7-12.3,9.7
|
||||
c-19,7.4-38.1,14.8-57.1,22.2c12.4,15.2,39.3,10.6,51.9,25.7c1.9,2.3,3.5,5.2,3.2,8.2c-0.6,7.1-9.4,9.7-16.5,10.6
|
||||
c-31.4,4-62.8,7.9-94.2,11.9c3.7,7.3,7.5,14.7,11.2,22C613.6,495.3,546.3,489.3,482,483c50.2,28.1,105.3,45,161.9,56.7
|
||||
c108,11.1,334.9,8.7,361.7-11.3C1025.1,513.7,924.8,453.4,819,414.2z"/>
|
||||
</g>
|
||||
<path class="st32" d="M818.4,253.1c7.3-30,7.6-61.8,0.8-91.9"/>
|
||||
<g>
|
||||
<path class="st17" d="M529.5,389.5c-105.8,15.2-203.2,42.9-214.2,48.4c-47.1,23.5,214.4,87.8,316.3,100.4s346.1,10.9,374-10
|
||||
c19.8-14.8-80.2-74.7-187-113.9"/>
|
||||
</g>
|
||||
<path class="st32" d="M521.6,404.3c45.3-92.8,92.7-184.5,142.2-275.1c6.9-12.7,14.3-25.8,25.9-34.3c9.2-6.7,20.3-10.1,31.3-12.9
|
||||
c15.8-4.1,31.8-7.3,48-9.6c9.8-1.4,20.2-2.4,29,2c6.9,3.4,11.9,9.8,16.5,16c13.2,17.8,25.4,36.3,36.5,55.5
|
||||
c8.9,15.4,17.9,32.2,33.6,40.7c15.7,8.5,40,3.1,43.9-14.3c0.5,21.6-10,43.2-27.2,56.3c-17.2,13.1-40.9,17.3-61.6,10.9
|
||||
c-4.8-1.5-10.2-3.4-14.6-0.9c-4,2.3-5.3,7.4-6.2,11.9c-12.3,65-9.7,132.7,7.5,196.6"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 24 KiB |
BIN
vendor/github.com/magefile/mage/site/static/images/gnorm.png
generated
vendored
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
vendor/github.com/magefile/mage/site/static/images/hugo.png
generated
vendored
Normal file
After Width: | Height: | Size: 24 KiB |
3
vendor/github.com/magefile/mage/site/themes/learn/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
.DS_Store
|
||||
public/
|
||||
exampleSite/public
|
21
vendor/github.com/magefile/mage/site/themes/learn/LICENSE.md
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Grav
|
||||
Copyright (c) 2016 MATHIEU CORNIC
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
49
vendor/github.com/magefile/mage/site/themes/learn/README.md
generated
vendored
Normal file
|
@ -0,0 +1,49 @@
|
|||
# Hugo Learn Theme
|
||||
|
||||
This repository contains a theme for [Hugo](https://gohugo.io/), based on great [Grav Learn Theme](http://learn.getgrav.org/).
|
||||
|
||||
Visit the [theme documentation](https://learn.netlify.com/en/) to see what is going on. It is actually built with this theme.
|
||||
|
||||
## Main features
|
||||
|
||||
- Automatic Search
|
||||
- Multilingual mode
|
||||
- Unlimited menu levels
|
||||
- Automatic next/prev buttons to navigate through menu entries
|
||||
- Image resizing, shadow…
|
||||
- Attachments files
|
||||
- List child pages
|
||||
- Mermaid diagram (flowchart, sequence, gantt)
|
||||
- Customizable look and feel and themes variants
|
||||
- Buttons, Tip/Note/Info/Warning boxes, Expand
|
||||
|
||||
## Installation
|
||||
|
||||
Navigate to your themes folder in your Hugo site and use the following commands:
|
||||
|
||||
```
|
||||
$ cd themes
|
||||
$ git clone https://github.com/matcornic/hugo-theme-learn.git
|
||||
```
|
||||
|
||||
Check that your Hugo version is minimum `0.25` with `hugo version`.
|
||||
|
||||
![Overview](https://github.com/matcornic/hugo-theme-learn/raw/master/images/tn.png)
|
||||
|
||||
## Usage
|
||||
|
||||
- [Visit the documentation](https://learn.netlify.com/en/)
|
||||
|
||||
## Download old versions (prior to 2.0.0)
|
||||
|
||||
If you need old version for compatibility purpose, either download [theme source code from releases](https://github.com/matcornic/hugo-theme-learn/releases) or use the right git tag. For example, with `1.1.0`
|
||||
|
||||
- Direct download way: https://github.com/matcornic/hugo-theme-learn/archive/1.1.0.zip
|
||||
- Git way:
|
||||
|
||||
```shell
|
||||
cd themes/hugo-theme-learn
|
||||
git checkout tags/1.1.0
|
||||
```
|
||||
|
||||
For both solutions, the documentation is available at https://github.com/matcornic/hugo-theme-learn/releases/download/1.1.0/hugo-learn-doc-1.1.0.zip
|
13
vendor/github.com/magefile/mage/site/themes/learn/archetypes/chapter.md
generated
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
+++
|
||||
title = "{{ replace .TranslationBaseName "-" " " | title }}"
|
||||
date = {{ .Date }}
|
||||
weight = 5
|
||||
chapter = true
|
||||
pre = "<b>X. </b>"
|
||||
+++
|
||||
|
||||
### Chapter X
|
||||
|
||||
# Some Chapter title
|
||||
|
||||
Lorem Ipsum.
|
7
vendor/github.com/magefile/mage/site/themes/learn/archetypes/default.md
generated
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
+++
|
||||
title = "{{ replace .TranslationBaseName "-" " " | title }}"
|
||||
date = {{ .Date }}
|
||||
weight = 5
|
||||
+++
|
||||
|
||||
Lorem Ipsum.
|
20
vendor/github.com/magefile/mage/site/themes/learn/exampleSite/LICENSE.md
generated
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 MATHIEU CORNIC
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
39
vendor/github.com/magefile/mage/site/themes/learn/exampleSite/README.md
generated
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
- récriture doc -> TODO
|
||||
- créer une section Showcase
|
||||
- Menus déroulants icone -> TODO
|
||||
|
||||
- créer des jolis thèmes de base (avec des noms ou au moins de meilleures couleurs) -> DOING
|
||||
- Thème blue : OK
|
||||
- Thème red: OK
|
||||
- Theme green: OK
|
||||
- Passer a Wercker -> OK
|
||||
- corriger le multilangue pour la recherche et les autres ressources statiques : OK
|
||||
- Section "MORE" -> OK
|
||||
- ajouter les childs -> OK
|
||||
- ajouter les attachments -> OK
|
||||
- refaire la possibilité d'overrider le style/script/etc -> OK
|
||||
- sticky bar -> OK
|
||||
- ajouter Travis pour tester le thème quotidiennement avec les nouvelles versions de Hugo -> OK
|
||||
- #54 -> OK
|
||||
- corriger slider menu qui ne fonctionne plus -> OK
|
||||
- Update font awesome -> OK
|
||||
- internationalisation -> OK
|
||||
- Messages: OK
|
||||
- Ajouter un bouton pour changer de langue : OK
|
||||
- netlify -> OK
|
||||
- home page -> OK
|
||||
- réintégrer la doc dans le même repo -> OK
|
||||
- récupérer les shortcodes utiles -> OK
|
||||
- expand : OK
|
||||
- mermaid : OK
|
||||
- chapter -> OK
|
||||
- recherche (avec pointage à la première occurence sur la page) -> OK
|
||||
- visited links -> OK
|
||||
- disable Search -> OK
|
||||
- vérifier que ça fonctionne avec une base url -> OK
|
||||
- tester les affichages de page enfant -> OK
|
||||
- comprendre l'histoire de pagination -> OK
|
||||
- améliorer les couleurs de surlignement de highlightjs -> OK
|
||||
- créer les archetypes -> OK
|
||||
-> créé ceux de base -> OK
|
||||
-> vérifier la possibilité de générer automatiquement le bon weight -> OK
|
73
vendor/github.com/magefile/mage/site/themes/learn/exampleSite/config.toml
generated
vendored
Normal file
|
@ -0,0 +1,73 @@
|
|||
baseURL = "/"
|
||||
languageCode = "en-US"
|
||||
defaultContentLanguage = "en"
|
||||
|
||||
title = "Hugo Learn Documentation"
|
||||
theme = "hugo-theme-learn"
|
||||
themesdir = "../.."
|
||||
metaDataFormat = "yaml"
|
||||
defaultContentLanguageInSubdir= true
|
||||
|
||||
[params]
|
||||
editURL = "https://github.com/matcornic/hugo-theme-learn/edit/master/exampleSite/content/"
|
||||
description = "Documentation for Hugo Learn Theme"
|
||||
author = "Mathieu Cornic"
|
||||
showVisitedLinks = true
|
||||
|
||||
[outputs]
|
||||
home = [ "HTML", "RSS", "JSON"]
|
||||
|
||||
[Languages]
|
||||
[Languages.en]
|
||||
title = "Documentation for Hugo Learn Theme"
|
||||
weight = 1
|
||||
languageName = "English"
|
||||
|
||||
[[Languages.en.menu.shortcuts]]
|
||||
name = "<i class='fa fa-github'></i> Github repo"
|
||||
identifier = "ds"
|
||||
url = "https://github.com/matcornic/hugo-theme-learn"
|
||||
weight = 10
|
||||
|
||||
[[Languages.en.menu.shortcuts]]
|
||||
name = "<i class='fa fa-camera'></i> Showcases"
|
||||
url = "showcase"
|
||||
weight = 11
|
||||
|
||||
[[Languages.en.menu.shortcuts]]
|
||||
name = "<i class='fa fa-bookmark'></i> Hugo Documentation"
|
||||
identifier = "hugodoc"
|
||||
url = "https://gohugo.io/"
|
||||
weight = 20
|
||||
|
||||
[[Languages.en.menu.shortcuts]]
|
||||
name = "<i class='fa fa-bullhorn'></i> Credits"
|
||||
url = "/credits"
|
||||
weight = 30
|
||||
|
||||
[Languages.fr]
|
||||
title = "Documentation du thème Hugo Learn"
|
||||
weight = 2
|
||||
languageName = "Français"
|
||||
|
||||
[[Languages.fr.menu.shortcuts]]
|
||||
name = "<i class='fa fa-github'></i> Repo Github"
|
||||
identifier = "ds"
|
||||
url = "https://github.com/matcornic/hugo-theme-learn"
|
||||
weight = 10
|
||||
|
||||
[[Languages.fr.menu.shortcuts]]
|
||||
name = "<i class='fa fa-camera'></i> Vitrine"
|
||||
url = "/showcase"
|
||||
weight = 11
|
||||
|
||||
[[Languages.fr.menu.shortcuts]]
|
||||
name = "<i class='fa fa-bookmark'></i> Documentation Hugo"
|
||||
identifier = "hugodoc"
|
||||
url = "https://gohugo.io/"
|
||||
weight = 20
|
||||
|
||||
[[Languages.fr.menu.shortcuts]]
|
||||
name = "<i class='fa fa-bullhorn'></i> Crédits"
|
||||
url = "/credits"
|
||||
weight = 30
|
41
vendor/github.com/magefile/mage/site/themes/learn/exampleSite/content/_index.en.md
generated
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
---
|
||||
title: "Learn Theme for Hugo"
|
||||
---
|
||||
|
||||
# Hugo learn theme
|
||||
|
||||
[Hugo-theme-learn](http://github.com/matcornic/hugo-theme-learn) is a theme for [Hugo](https://gohugo.io/), a fast and modern static website engine written in Go. Where Hugo is often used for blogs, this multilingual-ready theme is **fully designed for documentation**.
|
||||
|
||||
This theme is a partial porting of the [Learn theme](http://learn.getgrav.org/) of [Grav](https://getgrav.org/), a modern flat-file CMS written in PHP.
|
||||
|
||||
{{% notice tip %}}Learn theme works with a _page tree structure_ to organize content : All contents are pages, which belong to other pages. [read more about this]({{%relref "cont/pages/_index.md"%}})
|
||||
{{% /notice %}}
|
||||
|
||||
## Main features
|
||||
|
||||
* [Automatic Search]({{%relref "basics/configuration/_index.md" %}})
|
||||
* [Multilingual mode]({{%relref "cont/i18n/_index.md" %}})
|
||||
* **Unlimited menu levels**
|
||||
* **Automatic next/prev buttons to navigate through menu entries**
|
||||
* [Image resizing, shadow...]({{%relref "cont/markdown.en.md#images" %}})
|
||||
* [Attachments files]({{%relref "shortcodes/attachments.en.md" %}})
|
||||
* [List child pages]({{%relref "shortcodes/children/_index.md" %}})
|
||||
* [Mermaid diagram]({{%relref "shortcodes/mermaid.en.md" %}}) (flowchart, sequence, gantt)
|
||||
* [Customizable look and feel and themes variants]({{%relref "basics/configuration/_index.md"%}})
|
||||
* [Buttons]({{%relref "shortcodes/button.en.md" %}}), [Tip/Note/Info/Warning boxes]({{%relref "shortcodes/notice.en.md" %}}), [Expand]({{%relref "shortcodes/expand.en.md" %}})
|
||||
|
||||
![Screenshot](https://github.com/matcornic/hugo-theme-learn/raw/master/images/screenshot.png?width=40pc&classes=shadow)
|
||||
|
||||
## Contribute to this documentation
|
||||
Feel free to update this content, just click the **Edit this page** link displayed on top right of each page, and pullrequest it
|
||||
|
||||
{{% notice info %}}
|
||||
Your modification will be deployed automatically when merged.
|
||||
{{% /notice %}}
|
||||
|
||||
## Documentation website
|
||||
This current documentation has been statically generated with Hugo with a simple command : `hugo -t hugo-theme-learn` -- source code is [available here at GitHub](https://github.com/matcornic/hugo-theme-learn)
|
||||
|
||||
{{% notice note %}}
|
||||
Automatically published and hosted thanks to [Netlify](https://www.netlify.com/). Read more about [Automated HUGO deployments with Netlify](https://www.netlify.com/blog/2015/07/30/hosting-hugo-on-netlifyinsanely-fast-deploys/)
|
||||
{{% /notice %}}
|
43
vendor/github.com/magefile/mage/site/themes/learn/exampleSite/content/_index.fr.md
generated
vendored
Normal file
|
@ -0,0 +1,43 @@
|
|||
---
|
||||
title: "Learn Theme for Hugo"
|
||||
---
|
||||
|
||||
# Thème Hugo learn
|
||||
|
||||
[Hugo-theme-learn](http://github.com/matcornic/hugo-theme-learn) est un thème pour [Hugo](https://gohugo.io/), un générateur de site statique, rapide et modern, écrit en Go. Tandis que Hugo est souvent utilisé pour des blogs, ce thème multi-langue est **entièrement conçu pour la documentation**.
|
||||
|
||||
Ce thème est un portage partiel du [thème Learn](http://learn.getgrav.org/) de [Grav](https://getgrav.org/), un CMS modern écrit en PHP.
|
||||
|
||||
{{% notice tip %}}Le thème Learn fonctionne grâce à la structure de page aborescentes pour organiser le contenu: tous les contenus sont des pages qui appartiennent à d'autres pages. [Plus d'infos]({{%relref "cont/pages/_index.md"%}})
|
||||
{{% /notice %}}
|
||||
|
||||
## Fonctionnalité principales
|
||||
|
||||
* [Recherche automatique]({{%relref "basics/configuration/_index.md" %}})
|
||||
* [Mode multi-langue]({{%relref "cont/i18n/_index.md" %}})
|
||||
* **Nombre de niveau infini dans le menu**
|
||||
* **Boutons suivant/précédent automatiquement générés pour naviguer entre les items du menu**
|
||||
* [Taille d'image, ombres...]({{%relref "cont/markdown.fr.md#images" %}})
|
||||
* [Fichiers joints]({{%relref "shortcodes/attachments.fr.md" %}})
|
||||
* [Lister les pages filles]({{%relref "shortcodes/children/_index.md" %}})
|
||||
* [Diagrammes Mermaid]({{%relref "shortcodes/mermaid.fr.md" %}}) (flowchart, sequence, gantt)
|
||||
* [Style configurable and variantes de couleurs]({{%relref "basics/configuration/_index.md"%}})
|
||||
* [Boutons]({{%relref "shortcodes/button.fr.md" %}}), [Messages Astuce/Note/Info/Attention]({{%relref "shortcodes/notice.fr.md" %}}), [Expand]({{%relref "shortcodes/expand.fr.md" %}})
|
||||
|
||||
![Screenshot](https://github.com/matcornic/hugo-theme-learn/raw/master/images/screenshot.png?width=40pc&classes=shadow)
|
||||
|
||||
## Contribuer à cette documentation
|
||||
|
||||
N'hésitez pas à mettre à jour ce contenu en cliquant sur le lien **Modifier cette page** en haut de chaque page, et créer la Pull Request associée.
|
||||
|
||||
{{% notice info %}}
|
||||
Votre modification sera déployée automatiquement quand elle sera mergée.
|
||||
{{% /notice %}}
|
||||
|
||||
## Site de documentation
|
||||
|
||||
Cette documentation statique a été générée avec Hugo avec une simple commande : `hugo -t hugo-theme-learn` -- le code source est [disponible sur Github](https://github.com/matcornic/hugo-theme-learn)
|
||||
|
||||
{{% notice note %}}
|
||||
Le site est auomatiquement publié et hébergé par [Netlify](https://www.netlify.com/). Plus d'infos sur le [déploiement de site Hugo avec Netlify](https://www.netlify.com/blog/2015/07/30/hosting-hugo-on-netlifyinsanely-fast-deploys/)(En anglais)
|
||||
{{% /notice %}}
|
12
vendor/github.com/magefile/mage/site/themes/learn/exampleSite/content/basics/_index.en.md
generated
vendored
Executable file
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
title: Basics
|
||||
weight: 5
|
||||
pre: "<b>1. </b>"
|
||||
chapter: true
|
||||
---
|
||||
|
||||
### Chapter 1
|
||||
|
||||
# Basics
|
||||
|
||||
Discover what this Hugo theme is all about and the core-concepts behind it.
|
12
vendor/github.com/magefile/mage/site/themes/learn/exampleSite/content/basics/_index.fr.md
generated
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
title: Démarrage
|
||||
weight: 5
|
||||
pre: "<b>1. </b>"
|
||||
chapter: true
|
||||
---
|
||||
|
||||
### Chapitre 1
|
||||
|
||||
# Démarrage
|
||||
|
||||
Découvrez comment utiliser ce thème Hugo et apprenez en les concepts
|
246
vendor/github.com/magefile/mage/site/themes/learn/exampleSite/content/basics/configuration/_index.en.md
generated
vendored
Normal file
|
@ -0,0 +1,246 @@
|
|||
---
|
||||
date: 2016-04-09T16:50:16+02:00
|
||||
title: Configuration
|
||||
weight: 20
|
||||
---
|
||||
|
||||
## Global site parameters
|
||||
|
||||
On top of [Hugo global configuration](https://gohugo.io/overview/configuration/), **Hugo-theme-learn** lets you define the following parameters in your `config.toml` (here, values are default).
|
||||
|
||||
Note that some of these parameters are explained in details in other sections of this documentation.
|
||||
|
||||
```toml
|
||||
[params]
|
||||
# Prefix URL to edit current page. Will display an "Edit this page" button on top right hand corner of every page.
|
||||
# Useful to give opportunity to people to create merge request for your doc.
|
||||
# See the config.toml file from this documentation site to have an example.
|
||||
editURL = ""
|
||||
# Author of the site, will be used in meta information
|
||||
author = ""
|
||||
# Description of the site, will be used in meta information
|
||||
description = ""
|
||||
# Shows a checkmark for visited pages on the menu
|
||||
showVisitedLinks = false
|
||||
# Disable search function. It will hide search bar
|
||||
disableSearch = false
|
||||
# Javascript and CSS cache are automatically busted when new version of site is generated.
|
||||
# Set this to true to disable this behavior (some proxies don't handle well this optimization)
|
||||
disableAssetsBusting = false
|
||||
# Set this to true to disable copy-to-clipboard button for inline code.
|
||||
disableInlineCopyToClipBoard = false
|
||||
# A title for shortcuts in menu is set by default. Set this to true to disable it.
|
||||
disableShortcutsTitle = false
|
||||
# When using mulitlingual website, disable the switch language button.
|
||||
disableLanguageSwitchingButton = false
|
||||
# Order sections in menu by "weight" or "title". Default to "weight"
|
||||
ordersectionsby = "weight"
|
||||
# Change default color scheme with a variant one. Can be "red", "blue", "green".
|
||||
themeVariant = ""
|
||||
```
|
||||
|
||||
## Activate search
|
||||
|
||||
If not already present, add the follow lines in the same `config.toml` file.
|
||||
|
||||
```toml
|
||||
[outputs]
|
||||
home = [ "HTML", "RSS", "JSON"]
|
||||
```
|
||||
|
||||
Learn theme uses the last improvement available in hugo version 20+ to generate a json index file ready to be consumed by lunr.js javascript search engine.
|
||||
|
||||
> Hugo generate lunrjs index.json at the root of public folder.
|
||||
> When you build the site with hugo server, hugo generates it internally and of course it don’t show up in the filesystem
|
||||
|
||||
|
||||
## Style customization
|
||||
|
||||
**Hugo-theme-learn** has been built to be as configurable as possible by defining multiple [partials](https://gohugo.io/templates/partials/)
|
||||
|
||||
In `themes/hugo-theme-learn/layouts/partials/`, you will find all the partials defined for this theme. If you need to overwrite something, don't change the code directly. Instead [follow this page](https://gohugo.io/themes/customizing/). You'd create a new partial in the `layouts/partials` folder of your local project. This partial will have the priority.
|
||||
|
||||
This theme defines the following partials :
|
||||
|
||||
- *header*: the header of the content page (contains the breadcrumbs). _Not meant to be overwritten_
|
||||
- *custom-header*: custom headers in page. Meant to be overwritten when adding CSS imports. Don't forget to include `style` HTML tag directive in your file
|
||||
- *footer*: the footer of the content page (contains the arrows). _Not meant to be overwritten_
|
||||
- *custom-footer*: custom footer in page. Meant to be overwritten when adding Javacript. Don't forget to include `javascript` HTML tag directive in your file
|
||||
- *favicon*: the favicon
|
||||
- *logo*: the logo, on top left hand corner.
|
||||
- *meta*: HTML meta tags, if you want to change default behavior
|
||||
- *menu*: left menu. _Not meant to be overwritten_
|
||||
- *menu-footer*: footer of the the left menu
|
||||
- *search*: search box
|
||||
- *toc*: table of contents
|
||||
|
||||
### Change the logo
|
||||
|
||||
Create a new file in `layouts/partials/` named `logo.html`. Then write any HTML you want.
|
||||
You could use an `img` HTML tag and reference an image created under the *static* folder, or you could paste a SVG definition !
|
||||
|
||||
{{% notice note %}}
|
||||
The size of the logo will adapt automatically
|
||||
{{% /notice %}}
|
||||
|
||||
### Change the favicon
|
||||
|
||||
If your favicon is a png, just drop off your image in your local `static/images/` folder and names it `favicon.png`
|
||||
|
||||
If you need to change this default behavior, create a new file in `layouts/partials/` named `favicon.html`. Then write something like this:
|
||||
|
||||
```html
|
||||
<link rel="shortcut icon" href="/images/favicon.png" type="image/x-icon" />
|
||||
```
|
||||
|
||||
### Change default colors {#theme-variant}
|
||||
|
||||
**Hugo Learn theme** let you choose between 3 native color scheme variants, but feel free to add one yourself ! Default color scheme is based on [Grav Learn Theme](https://learn.getgrav.org/).
|
||||
|
||||
#### Red variant
|
||||
|
||||
```toml
|
||||
[params]
|
||||
# Change default color scheme with a variant one. Can be "red", "blue", "green".
|
||||
themeVariant = "red"
|
||||
```
|
||||
|
||||
![Red variant](/basics/configuration/images/red-variant.png?width=60%)
|
||||
|
||||
#### Blue variant
|
||||
|
||||
```toml
|
||||
[params]
|
||||
# Change default color scheme with a variant one. Can be "red", "blue", "green".
|
||||
themeVariant = "blue"
|
||||
```
|
||||
|
||||
![Blue variant](/basics/configuration/images/blue-variant.png?width=60%)
|
||||
|
||||
#### Green variant
|
||||
|
||||
```toml
|
||||
[params]
|
||||
# Change default color scheme with a variant one. Can be "red", "blue", "green".
|
||||
themeVariant = "green"
|
||||
```
|
||||
|
||||
![Green variant](/basics/configuration/images/green-variant.png?width=60%)
|
||||
|
||||
#### 'Yours‘ variant
|
||||
|
||||
First, create a new CSS file in your local `static/css` folder prefixed by `theme` (e.g. with _mine_ theme `static/css/theme-mine.css`). Copy the following content and modify colors in CSS variables.
|
||||
|
||||
```css
|
||||
|
||||
:root{
|
||||
|
||||
--MAIN-TEXT-color:#323232; /* Color of text by default */
|
||||
--MAIN-TITLES-TEXT-color: #5e5e5e; /* Color of titles h2-h3-h4-h5 */
|
||||
--MAIN-LINK-color:#1C90F3; /* Color of links */
|
||||
--MAIN-LINK-HOVER-color:#167ad0; /* Color of hovered links */
|
||||
--MAIN-ANCHOR-color: #1C90F3; /* color of anchors on titles */
|
||||
|
||||
--MENU-HEADER-BG-color:#1C90F3; /* Background color of menu header */
|
||||
--MENU-HEADER-BORDER-color:#33a1ff; /*Color of menu header border */
|
||||
|
||||
--MENU-SEARCH-BG-color:#167ad0; /* Search field background color (by default borders + icons) */
|
||||
--MENU-SEARCH-BOX-color: #33a1ff; /* Override search field border color */
|
||||
--MENU-SEARCH-BOX-ICONS-color: #a1d2fd; /* Override search field icons color */
|
||||
|
||||
--MENU-SECTIONS-ACTIVE-BG-color:#20272b; /* Background color of the active section and its childs */
|
||||
--MENU-SECTIONS-BG-color:#252c31; /* Background color of other sections */
|
||||
--MENU-SECTIONS-LINK-color: #ccc; /* Color of links in menu */
|
||||
--MENU-SECTIONS-LINK-HOVER-color: #e6e6e6; /* Color of links in menu, when hovered */
|
||||
--MENU-SECTION-ACTIVE-CATEGORY-color: #777; /* Color of active category text */
|
||||
--MENU-SECTION-ACTIVE-CATEGORY-BG-color: #fff; /* Color of background for the active category (only) */
|
||||
|
||||
--MENU-VISITED-color: #33a1ff; /* Color of 'page visited' icons in menu */
|
||||
--MENU-SECTION-HR-color: #20272b; /* Color of <hr> separator in menu */
|
||||
|
||||
}
|
||||
|
||||
body {
|
||||
color: var(--MAIN-TEXT-color) !important;
|
||||
}
|
||||
|
||||
textarea:focus, input[type="email"]:focus, input[type="number"]:focus, input[type="password"]:focus, input[type="search"]:focus, input[type="tel"]:focus, input[type="text"]:focus, input[type="url"]:focus, input[type="color"]:focus, input[type="date"]:focus, input[type="datetime"]:focus, input[type="datetime-local"]:focus, input[type="month"]:focus, input[type="time"]:focus, input[type="week"]:focus, select[multiple=multiple]:focus {
|
||||
border-color: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
h2, h3, h4, h5 {
|
||||
color: var(--MAIN-TITLES-TEXT-color) !important;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--MAIN-LINK-color);
|
||||
}
|
||||
|
||||
.anchor {
|
||||
color: var(--MAIN-ANCHOR-color);
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: var(--MAIN-LINK-HOVER-color);
|
||||
}
|
||||
|
||||
#sidebar ul li.visited > a .read-icon {
|
||||
color: var(--MENU-VISITED-color);
|
||||
}
|
||||
|
||||
#body a.highlight:after {
|
||||
display: block;
|
||||
content: "";
|
||||
height: 1px;
|
||||
width: 0%;
|
||||
-webkit-transition: width 0.5s ease;
|
||||
-moz-transition: width 0.5s ease;
|
||||
-ms-transition: width 0.5s ease;
|
||||
transition: width 0.5s ease;
|
||||
background-color: var(--MAIN-HOVER-color);
|
||||
}
|
||||
#sidebar {
|
||||
background-color: var(--MENU-SECTIONS-BG-color);
|
||||
}
|
||||
#sidebar #header-wrapper {
|
||||
background: var(--MENU-HEADER-BG-color);
|
||||
color: var(--MENU-SEARCH-BOX-color);
|
||||
border-color: var(--MENU-HEADER-BORDER-color);
|
||||
}
|
||||
#sidebar .searchbox {
|
||||
border-color: var(--MENU-SEARCH-BOX-color);
|
||||
background: var(--MENU-SEARCH-BG-color);
|
||||
}
|
||||
#sidebar ul.topics > li.parent, #sidebar ul.topics > li.active {
|
||||
background: var(--MENU-SECTIONS-ACTIVE-BG-color);
|
||||
}
|
||||
#sidebar .searchbox * {
|
||||
color: var(--MENU-SEARCH-BOX-ICONS-color);
|
||||
}
|
||||
|
||||
#sidebar a {
|
||||
color: var(--MENU-SECTIONS-LINK-color);
|
||||
}
|
||||
|
||||
#sidebar a:hover {
|
||||
color: var(--MENU-SECTIONS-LINK-HOVER-color);
|
||||
}
|
||||
|
||||
#sidebar ul li.active > a {
|
||||
background: var(--MENU-SECTION-ACTIVE-CATEGORY-BG-color);
|
||||
color: var(--MENU-SECTION-ACTIVE-CATEGORY-color) !important;
|
||||
}
|
||||
|
||||
#sidebar hr {
|
||||
border-color: var(--MENU-SECTION-HR-color);
|
||||
}
|
||||
```
|
||||
|
||||
Then, set the `themeVariant` value with the name of your custom theme file. That's it !
|
||||
|
||||
```toml
|
||||
[params]
|
||||
# Change default color scheme with a variant one. Can be "red", "blue", "green".
|
||||
themeVariant = "mine"
|
||||
```
|
245
vendor/github.com/magefile/mage/site/themes/learn/exampleSite/content/basics/configuration/_index.fr.md
generated
vendored
Normal file
|
@ -0,0 +1,245 @@
|
|||
---
|
||||
date: 2016-04-09T16:50:16+02:00
|
||||
title: Configuration
|
||||
weight: 20
|
||||
---
|
||||
|
||||
## Global site parameters
|
||||
|
||||
En plus de la [configuration globale d'Hugo](https://gohugo.io/overview/configuration/), **Hugo-theme-learn** vous permet de définir les paramètres suivant dans votre fichier `config.toml` (ci-dessous sont affichées les valeurs par défaut).
|
||||
|
||||
Notez que certains de ces paramètres sont expliqués en détails dans d'autres sections de cette documentation.
|
||||
|
||||
```toml
|
||||
[params]
|
||||
# L'URL préfixe pour éditer la page courante. Ce paramètre affichera un bouton "Modifier cette page" on haut de de chacune des pages.
|
||||
# Pratique pour donner les possibilité à vos utilisateurs de créer une merge request pour votre doc.
|
||||
# Allez voir le fichier config.toml de cette documentation pour avoir un exemple.
|
||||
editURL = ""
|
||||
# Autheur du site, est utilisé dans les informations meta
|
||||
author = ""
|
||||
# Description du site, est utilisé dans les informations meta
|
||||
description = ""
|
||||
# Affiche une icône lorsque la page a été visitée
|
||||
showVisitedLinks = false
|
||||
# Désactive la fonction de recherche. Une valeur à true cache la barre de recherche.
|
||||
disableSearch = false
|
||||
# Par défaut, le cache Javascript et CSS est automatiquement vidé lorsqu'une nouvelle version du site est générée.
|
||||
# Utilisez ce paramètre lorsque vous voulez désactiver ce comportement (c'est parfois incompatible avec certains proxys)
|
||||
disableAssetsBusting = false
|
||||
# Utilisez ce paramètre pour désactiver le bouton copy-to-clipboard pour le code formatté sur une ligne.
|
||||
disableInlineCopyToClipBoard = false
|
||||
# Un titre est défini par défaut lorsque vous utilisez un raccourci dans le menu. Utilisez ce paramètre pour le cacher.
|
||||
disableShortcutsTitle = false
|
||||
# Quand vous utilisez un site multi-langue, utilisez ce paramètre pour désactiver le bouton de changement de langue.
|
||||
disableLanguageSwitchingButton = false
|
||||
# Ordonne les sections dans menu par poids ("weight") ou titre ("title"). Défaut à "weight"
|
||||
ordersectionsby = "weight"
|
||||
# Utilisez ce paramètre pour modifier le schéma de couleur du site. Les valeurs par défaut sont "red", "blue", "green".
|
||||
themeVariant = ""
|
||||
```
|
||||
|
||||
## Activez la recherche
|
||||
|
||||
Si ce n'est pas déjà présent, ajoutez les lignes suivantes dans le fichier `config.toml`.
|
||||
|
||||
```toml
|
||||
[outputs]
|
||||
home = [ "HTML", "RSS", "JSON"]
|
||||
```
|
||||
|
||||
Le thème *Learn* utilise les dernières amélioraions d'Hugo pour générer un fichier d'index JSON, prêt à être consommé par le moteur de recherche lunr.js.
|
||||
|
||||
> Hugo génère lunrjs index.json à la racine du dossier `public`.
|
||||
> Quand vous générez le site avec `hugo server`, Hugo génère le fichier en mémoire, il n'est donc pas disponible sur le disque.
|
||||
|
||||
## Personnaliser le style
|
||||
|
||||
**Hugo-theme-learn** a été conçu pour être aussi configurable que possible en définissant plusieurs [partials](https://gohugo.io/templates/partials/)
|
||||
|
||||
Dans `themes/hugo-theme-learn/layouts/partials/`, vous pourrez trouver tous les *partials* définis pour ce thème. Si vous avez besoin d'écraser quelque chose, ne modifiez pas le code directement. A la place, [suivez cette page](https://gohugo.io/themes/customizing/). Vous créerez alors un nouveau *partial* dans le dossier `layouts/partials` de votre site local. Ce *partial* aura la priorité.
|
||||
|
||||
Ce thème définit les *partials* suivant :
|
||||
|
||||
- *header*: l'en-tête de la page page (contient le fil d'Ariane). _Pas voué à être écrasé_
|
||||
- *custom-header*: En-tête personnalisé. Voué à être écrasé quand vous ajoutez des imports CSS. N'oubliez pas d'inclure la balise HTML `style` dans votre fichier
|
||||
- *footer*: le pied-de-page de la page (contains les flèches). _Pas voué à être écrasé_
|
||||
- *custom-footer*: Pied-de-page personnalisé. Voué à être écrasé quand vous ajoutez du Javascript. N'oubliez pas d'inclure la balise HTML `javascript` dans votre fichier
|
||||
- *favicon*: le favicon
|
||||
- *logo*: le logo, affiché un haut à gauche.
|
||||
- *meta*: les balises HTML meta, que vous pouvez écraser sans problème.
|
||||
- *menu*: Le menu à gauche. _Pas voué à être écrasé_
|
||||
- *menu-footer*: Le pied-de-page du menu
|
||||
- *search*: le champ de recherche
|
||||
- *toc*: le sommaire
|
||||
|
||||
### Changer le logo
|
||||
|
||||
Créez un nouveau fichier dans `layouts/partials/`, nommé `logo.html`. Puis, écrivez le code HTML voulu.
|
||||
Vous pourriez utiliser une balise HTML `img` et référencer une image créée dans le dossier *static*, voire même y coller un cod SVG !
|
||||
|
||||
{{% notice note %}}
|
||||
La taille du logo va s'adapter automatiquement
|
||||
{{% /notice %}}
|
||||
|
||||
### Changer le favicon
|
||||
|
||||
Si votre favicon est un png, déposez votre image dans votre dossier local `static/images/` et nommez le `favicon.png`
|
||||
|
||||
Si vous avez besoin de changer ce comportement par défaut, créer un nouveau fichier dans `layouts/partials/` et nommez le `favicon.html`. Puis ajoutez quelque chose comme:
|
||||
|
||||
```html
|
||||
<link rel="shortcut icon" href="/images/favicon.png" type="image/x-icon" />
|
||||
```
|
||||
|
||||
### Changer les couleurs par défaut {#theme-variant}
|
||||
|
||||
**Hugo Learn theme** vous permet de choisir nativement entre 3 schéma de couleurs, mais n'hésitez pas à en ajouter d'autres ! Les couleurs par défaut sont celles de [Grav Learn Theme](https://learn.getgrav.org/).
|
||||
|
||||
#### Variante rouge
|
||||
|
||||
```toml
|
||||
[params]
|
||||
# Modifier le schéma de couleur par défaut. Peut être "red", "blue", "green".
|
||||
themeVariant = "red"
|
||||
```
|
||||
|
||||
![Variante rouge](/basics/configuration/images/red-variant.png?width=60%)
|
||||
|
||||
#### Variante bleue
|
||||
|
||||
```toml
|
||||
[params]
|
||||
# Modifier le schéma de couleur par défaut. Peut être "red", "blue", "green".
|
||||
themeVariant = "blue"
|
||||
```
|
||||
|
||||
![Variante bleue](/basics/configuration/images/blue-variant.png?width=60%)
|
||||
|
||||
#### Variante verte
|
||||
|
||||
```toml
|
||||
[params]
|
||||
# Modifier le schéma de couleur par défaut. Peut être "red", "blue", "green".
|
||||
themeVariant = "green"
|
||||
```
|
||||
|
||||
![Variante verte](/basics/configuration/images/green-variant.png?width=60%)
|
||||
|
||||
#### Votre variante
|
||||
|
||||
Premièrement, créez un nouveau fichier CSS dans votre dossier `static/css`, préfixé par `theme` (ex: avec le theme_lemien_ `static/css/theme-lemien.css`). Copiez le contenu suivant et modifiez les couleurs dans les variables CSS.
|
||||
|
||||
```css
|
||||
|
||||
:root{
|
||||
|
||||
--MAIN-TEXT-color:#323232; /* Color of text by default */
|
||||
--MAIN-TITLES-TEXT-color: #5e5e5e; /* Color of titles h2-h3-h4-h5 */
|
||||
--MAIN-LINK-color:#1C90F3; /* Color of links */
|
||||
--MAIN-LINK-HOVER-color:#167ad0; /* Color of hovered links */
|
||||
--MAIN-ANCHOR-color: #1C90F3; /* color of anchors on titles */
|
||||
|
||||
--MENU-HEADER-BG-color:#1C90F3; /* Background color of menu header */
|
||||
--MENU-HEADER-BORDER-color:#33a1ff; /*Color of menu header border */
|
||||
|
||||
--MENU-SEARCH-BG-color:#167ad0; /* Search field background color (by default borders + icons) */
|
||||
--MENU-SEARCH-BOX-color: #33a1ff; /* Override search field border color */
|
||||
--MENU-SEARCH-BOX-ICONS-color: #a1d2fd; /* Override search field icons color */
|
||||
|
||||
--MENU-SECTIONS-ACTIVE-BG-color:#20272b; /* Background color of the active section and its childs */
|
||||
--MENU-SECTIONS-BG-color:#252c31; /* Background color of other sections */
|
||||
--MENU-SECTIONS-LINK-color: #ccc; /* Color of links in menu */
|
||||
--MENU-SECTIONS-LINK-HOVER-color: #e6e6e6; /* Color of links in menu, when hovered */
|
||||
--MENU-SECTION-ACTIVE-CATEGORY-color: #777; /* Color of active category text */
|
||||
--MENU-SECTION-ACTIVE-CATEGORY-BG-color: #fff; /* Color of background for the active category (only) */
|
||||
|
||||
--MENU-VISITED-color: #33a1ff; /* Color of 'page visited' icons in menu */
|
||||
--MENU-SECTION-HR-color: #20272b; /* Color of <hr> separator in menu */
|
||||
|
||||
}
|
||||
|
||||
body {
|
||||
color: var(--MAIN-TEXT-color) !important;
|
||||
}
|
||||
|
||||
textarea:focus, input[type="email"]:focus, input[type="number"]:focus, input[type="password"]:focus, input[type="search"]:focus, input[type="tel"]:focus, input[type="text"]:focus, input[type="url"]:focus, input[type="color"]:focus, input[type="date"]:focus, input[type="datetime"]:focus, input[type="datetime-local"]:focus, input[type="month"]:focus, input[type="time"]:focus, input[type="week"]:focus, select[multiple=multiple]:focus {
|
||||
border-color: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
h2, h3, h4, h5 {
|
||||
color: var(--MAIN-TITLES-TEXT-color) !important;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--MAIN-LINK-color);
|
||||
}
|
||||
|
||||
.anchor {
|
||||
color: var(--MAIN-ANCHOR-color);
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: var(--MAIN-LINK-HOVER-color);
|
||||
}
|
||||
|
||||
#sidebar ul li.visited > a .read-icon {
|
||||
color: var(--MENU-VISITED-color);
|
||||
}
|
||||
|
||||
#body a.highlight:after {
|
||||
display: block;
|
||||
content: "";
|
||||
height: 1px;
|
||||
width: 0%;
|
||||
-webkit-transition: width 0.5s ease;
|
||||
-moz-transition: width 0.5s ease;
|
||||
-ms-transition: width 0.5s ease;
|
||||
transition: width 0.5s ease;
|
||||
background-color: var(--MAIN-HOVER-color);
|
||||
}
|
||||
#sidebar {
|
||||
background-color: var(--MENU-SECTIONS-BG-color);
|
||||
}
|
||||
#sidebar #header-wrapper {
|
||||
background: var(--MENU-HEADER-BG-color);
|
||||
color: var(--MENU-SEARCH-BOX-color);
|
||||
border-color: var(--MENU-HEADER-BORDER-color);
|
||||
}
|
||||
#sidebar .searchbox {
|
||||
border-color: var(--MENU-SEARCH-BOX-color);
|
||||
background: var(--MENU-SEARCH-BG-color);
|
||||
}
|
||||
#sidebar ul.topics > li.parent, #sidebar ul.topics > li.active {
|
||||
background: var(--MENU-SECTIONS-ACTIVE-BG-color);
|
||||
}
|
||||
#sidebar .searchbox * {
|
||||
color: var(--MENU-SEARCH-BOX-ICONS-color);
|
||||
}
|
||||
|
||||
#sidebar a {
|
||||
color: var(--MENU-SECTIONS-LINK-color);
|
||||
}
|
||||
|
||||
#sidebar a:hover {
|
||||
color: var(--MENU-SECTIONS-LINK-HOVER-color);
|
||||
}
|
||||
|
||||
#sidebar ul li.active > a {
|
||||
background: var(--MENU-SECTION-ACTIVE-CATEGORY-BG-color);
|
||||
color: var(--MENU-SECTION-ACTIVE-CATEGORY-color) !important;
|
||||
}
|
||||
|
||||
#sidebar hr {
|
||||
border-color: var(--MENU-SECTION-HR-color);
|
||||
}
|
||||
```
|
||||
|
||||
Puis, configurez le paramètre `themeVariant` avec le nom de votre variante. C'est tout !
|
||||
|
||||
```toml
|
||||
[params]
|
||||
# Modifier le schéma de couleur par défaut. Peut être "red", "blue", "green".
|
||||
themeVariant = "lemien"
|
||||
```
|
BIN
vendor/github.com/magefile/mage/site/themes/learn/exampleSite/content/basics/configuration/images/blue-variant.png
generated
vendored
Normal file
After Width: | Height: | Size: 380 KiB |
BIN
vendor/github.com/magefile/mage/site/themes/learn/exampleSite/content/basics/configuration/images/green-variant.png
generated
vendored
Normal file
After Width: | Height: | Size: 382 KiB |
BIN
vendor/github.com/magefile/mage/site/themes/learn/exampleSite/content/basics/configuration/images/red-variant.png
generated
vendored
Normal file
After Width: | Height: | Size: 381 KiB |
100
vendor/github.com/magefile/mage/site/themes/learn/exampleSite/content/basics/installation/_index.en.md
generated
vendored
Normal file
|
@ -0,0 +1,100 @@
|
|||
---
|
||||
title: Installation
|
||||
weight: 15
|
||||
---
|
||||
|
||||
The following steps are here to help you initialize your new website. If you don't know Hugo at all, we strongly suggest you to train by following this [great documentation for beginners](https://gohugo.io/overview/quickstart/).
|
||||
|
||||
## Create your project
|
||||
|
||||
Hugo provides a `new` command to create a new website.
|
||||
|
||||
```
|
||||
hugo new site <new_project>
|
||||
```
|
||||
|
||||
## Install the theme
|
||||
|
||||
Install the **Hugo-theme-learn** theme by following [this documentation](https://gohugo.io/themes/installing/)
|
||||
|
||||
The theme's repository is: https://github.com/matcornic/hugo-theme-learn.git
|
||||
|
||||
Alternatively, you can [download the theme as .zip](https://github.com/matcornic/hugo-theme-learn/archive/master.zip) file and extract it in the themes directory
|
||||
|
||||
## Basic configuration
|
||||
|
||||
When building the website, you can set a theme by using `--theme` option. We suggest you to edit your configuration file and set the theme by default. By the way, add requirements for search functionnality to be enabled.
|
||||
|
||||
```toml
|
||||
# Change the default theme to be use when building the site with Hugo
|
||||
theme = "hugo-theme-learn"
|
||||
|
||||
# For search functionnality
|
||||
[outputs]
|
||||
home = [ "HTML", "RSS", "JSON"]
|
||||
```
|
||||
|
||||
## Create your first chapter page
|
||||
|
||||
Chapters are pages containing other child pages. It has a special layout style and usually just contains a _chapter name_, the _title_ and a _brief abstract_ of the section.
|
||||
|
||||
```
|
||||
### Chapter 1
|
||||
|
||||
# Basics
|
||||
|
||||
Discover what this Hugo theme is all about and the core-concepts behind it.
|
||||
```
|
||||
|
||||
renders as
|
||||
|
||||
![A Chapter](/basics/installation/images/chapter.png?classes=shadow&width=60%)
|
||||
|
||||
**Hugo-theme-learn** provides archetypes to create skeletons for your website. Begin by creating your first chapter page with the following command
|
||||
|
||||
```
|
||||
hugo new --kind chapter basics/_index.md
|
||||
```
|
||||
|
||||
By opening the given file, you should see the property `chapter=true` on top, meaning this page is a _chapter_.
|
||||
|
||||
## Create your first content pages
|
||||
|
||||
Then, create content pages inside the previous chapter. Here are two ways to create content in the chapter :
|
||||
|
||||
```
|
||||
hugo new basics/first-content.md
|
||||
hugo new basics/second-content/_index.md
|
||||
```
|
||||
|
||||
Feel free to edit thoses files by adding some sample content and replacing `title` value in the beginning of the files.
|
||||
|
||||
## Launching the website locally
|
||||
|
||||
Launch the following command:
|
||||
|
||||
```
|
||||
hugo serve
|
||||
```
|
||||
|
||||
Go to `http://localhost:1313`
|
||||
|
||||
You should notice three things:
|
||||
|
||||
1. You have a left **Basics** menu, containing two submenus with names equals to `title` properties in previously created files.
|
||||
2. The home page explains you to how to customize it. Follow the instructions.
|
||||
3. With `hugo serve` command, the page refresh as soon as you save a file. Neat !
|
||||
|
||||
## Build the website
|
||||
|
||||
When your site is ready to deploy, launch the following command:
|
||||
|
||||
```
|
||||
hugo
|
||||
```
|
||||
|
||||
A `public` folder has been generated, containing all statics content and assets for your website. It can now be deployed on any web server !
|
||||
|
||||
{{% notice note %}}
|
||||
This website can be automatically published and hosted with [Netlify](https://www.netlify.com/) (Read more about [Automated HUGO deployments with Netlify](https://www.netlify.com/blog/2015/07/30/hosting-hugo-on-netlifyinsanely-fast-deploys/)). Alternatively, you can use [Github pages](https://gohugo.io/hosting-and-deployment/hosting-on-github/)
|
||||
{{% /notice %}}
|
100
vendor/github.com/magefile/mage/site/themes/learn/exampleSite/content/basics/installation/_index.fr.md
generated
vendored
Normal file
|
@ -0,0 +1,100 @@
|
|||
---
|
||||
title: Installation
|
||||
weight: 15
|
||||
---
|
||||
|
||||
Les étapes suivantes sont là pour vous aider à initialiser votre site. Si vous ne connaissez pas du tout Hugo, il est fortement conseillé de vous entrainer en suivant ce [super tuto pour débutants](https://gohugo.io/overview/quickstart/).
|
||||
|
||||
## Créer votre projet
|
||||
|
||||
Hugo fournit une commande `new` pour créer un nouveau site.
|
||||
|
||||
```
|
||||
hugo new site <new_project>
|
||||
```
|
||||
|
||||
## Installer le thème
|
||||
|
||||
Installer le thème **Hugo-theme-learn** en suivant [cette documentation](https://gohugo.io/themes/installing/)
|
||||
|
||||
Le repo du thème est : https://github.com/matcornic/hugo-theme-learn.git
|
||||
|
||||
Sinon, vous pouvez [télécharger le thème sous forme d'un fichier .zip](https://github.com/matcornic/hugo-theme-learn/archive/master.zip) et extrayez le dans votre dossier de thèmes.
|
||||
|
||||
## Configuration simple
|
||||
|
||||
Lorsque vous générez votre site, vous pouvez définir un thème en utilisant l'option `--theme`. Il est conseillé de modifier votre fichier de configuration `config.toml` and définir votre thème par défaut. En passant, ajoutez les prérequis à l'utilisation de la fonctionnalité de recherche.
|
||||
|
||||
```toml
|
||||
# Modifiez le thème pour qu'il soit utilisé par défaut à chaque génération de site.
|
||||
theme = "hugo-theme-learn"
|
||||
|
||||
# Pour la fonctionnalité de recherche
|
||||
[outputs]
|
||||
home = [ "HTML", "RSS", "JSON"]
|
||||
```
|
||||
|
||||
## Créer votre première page chapitre
|
||||
|
||||
Les *chapitres* sont des pages contenant d'autre pages filles. Elles ont un affichage spécial et contiennent habituellement juste un _nom_ de chapitre, le _titre_ et un _résumé_ de la section.
|
||||
|
||||
```
|
||||
### Chapitre 1
|
||||
|
||||
# Démarrage
|
||||
|
||||
Découvrez comment utiliser ce thème Hugo et apprenez en les concepts
|
||||
```
|
||||
|
||||
s'affiche comme
|
||||
|
||||
![Un chapitre](/basics/installation/images/chapter.png?classes=shadow&width=60%)
|
||||
|
||||
**Hugo-theme-learn** fournit des archétypes pour créer des squelettes pour votre site. Commencez par créer votre premier chapitre avec la commande suivante:
|
||||
|
||||
```
|
||||
hugo new --kind chapter basics/_index.md
|
||||
```
|
||||
|
||||
En ouvrant le fichier généré, vous devriez voir la propriété `chapter=true` en haut, paramètre quit définit que le page est un _chapitre_.
|
||||
|
||||
## Créer votre première page
|
||||
|
||||
Puis, créez votre premier page dans le chapitre précédent. Pour ce faire, il existe deux possibilités :
|
||||
|
||||
```
|
||||
hugo new basics/first-content.md
|
||||
hugo new basics/second-content/_index.md
|
||||
```
|
||||
|
||||
N'hésitez pas à éditer ces fichiers en ajoutant des exemple de contenu et en remplaçant le paramètre `title` au début du fichier.
|
||||
|
||||
## Lancer le site localement
|
||||
|
||||
Lancez la commande suivante :
|
||||
|
||||
```
|
||||
hugo serve
|
||||
```
|
||||
|
||||
Se rendre sur `http://localhost:1313`
|
||||
|
||||
Vous devriez voir trois choses:
|
||||
|
||||
1. Vous avez un menu **Basics** à gauche, qui contient deux sous-menu avec des noms égal au paramètre `title` des fichiers précédemment générés.
|
||||
2. La page d'accueil vous explique comment la modifier. Suivez les instructions.
|
||||
3. Avec la commande `hugo serve`, la page se rafraichit automatiquement à chaque fois que vous sauvegardez. Super !
|
||||
|
||||
## Générez le site
|
||||
|
||||
Quand votre site est prêt à être déployé, lancez la commande suivante:
|
||||
|
||||
```
|
||||
hugo
|
||||
```
|
||||
|
||||
Un dossier `public` a été généré. Il contient tout le contenu statique et les ressources nécessaires pour votre site. Votre site peut maintenant être déployé en utilisant n'importe quel serveur !
|
||||
|
||||
{{% notice note %}}
|
||||
Ce site peut être automatiquement publié et hébergé avec [Netlify](https://www.netlify.com/) ([Plus d'infos](https://www.netlify.com/blog/2015/07/30/hosting-hugo-on-netlifyinsanely-fast-deploys/)). Sinon, vous pouvez utiliser les [Github pages](https://gohugo.io/hosting-and-deployment/hosting-on-github/)
|
||||
{{% /notice %}}
|
BIN
vendor/github.com/magefile/mage/site/themes/learn/exampleSite/content/basics/installation/images/chapter.png
generated
vendored
Normal file
After Width: | Height: | Size: 86 KiB |
11
vendor/github.com/magefile/mage/site/themes/learn/exampleSite/content/basics/requirements/_index.en.md
generated
vendored
Executable file
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
title: Requirements
|
||||
weight: 10
|
||||
disableToc: true
|
||||
---
|
||||
|
||||
Thanks to the simplicity of Hugo, this page is as empty as this theme needs requirements.
|
||||
|
||||
Just download latest version of [Hugo binary (> 0.25)](https://gohugo.io/getting-started/installing/) for your OS (Windows, Linux, Mac) : it's that simple.
|
||||
|
||||
![Magic](/basics/requirements/images/magic.gif?classes=shadow)
|