Compare commits

...

134 Commits
v2.5.2 ... v2

Author SHA1 Message Date
Andrey Nering
c7bb3d63b0 Merge pull request #349 from central182/fix-typo
Fix some typos in the documentation
2020-07-19 16:02:58 -03:00
Arnold
e6b543c15e Fix some typos in the documentation 2020-07-07 16:25:27 +09:00
Andrey Nering
7dcb3af944 Merge pull request #347 from ronvanderheijden/master
Completion file honors includes
2020-06-14 16:38:13 -03:00
Ron van der Heijden
10986d3a7c Accept : multiple times 2020-06-13 17:01:14 +02:00
Andrey Nering
bf64259af3 taskfile.dev: Add note about parallel deps
Reference: #331
2020-05-23 14:13:15 -03:00
Andrey Nering
6141ba84ce taskfile.dev: Switch completely from unpkg.com to jsdelivr.net 2020-05-23 14:00:38 -03:00
Andrey Nering
329902f0db taskfile.dev: Improve the installation page by using tabs 2020-05-23 13:46:03 -03:00
Andrey Nering
bfcaa7a443 taskfile.dev: Install Docsify Tabs plugin 2020-05-23 13:45:57 -03:00
Andrey Nering
45915bf0ed taskfile.dev: Remove tracking stuff 2020-05-23 13:45:50 -03:00
Andrey Nering
df8293bee6 v2.8.1 2020-05-20 19:26:23 -03:00
Andrey Nering
935216f179 Upgrade mvdan.cc/sh to v3.1.1 2020-05-20 19:22:27 -03:00
Andrey Nering
f56bbd46fd Fix typo 2020-05-18 13:16:50 -03:00
Andrey Nering
86be13ff1f Merge pull request #330 from danquah/print-usage
Have the --help/-h flag print usage.
2020-05-14 21:15:00 -03:00
Andrey Nering
ee95df0e57 Merge pull request #329 from danquah/version-print-std-out
Switch to printing the version string to std out
2020-05-14 21:12:43 -03:00
Andrey Nering
442c29f020 Merge pull request #328 from danquah/fix-goreleaser-name-template
Fix name_template in Go Releaser
2020-05-14 21:11:22 -03:00
Mads H. Danquah
739037fc37 Have the --help/-h flag print usage.
pflag will output a "pflag: help requested" message after displaying the usage
if we don't explicitly  handle the flag.
2020-05-14 21:58:46 +02:00
Mads H. Danquah
f8252020aa Switch to printing the version string to std out 2020-05-14 21:40:49 +02:00
Mads H. Danquah
38b87439fe name_template is now file_name_template
See https://goreleaser.com/deprecations/#nfpmsname_template
2020-05-14 20:48:33 +02:00
Chris Garrett
116879f7ea Update docs to reflect change from Travis to GitHub 2020-05-03 14:58:02 -03:00
Andrey Nering
2eafb2f067 Update CHANGELOG 2020-05-01 15:50:32 -03:00
Andrey Nering
c36f0f6f7f Merge pull request #317 from hatappi/master
suppress context errors when use watch option
2020-05-01 15:38:16 -03:00
hatappi
bfc033959b suppress context errors when use watch option 2020-04-29 11:56:02 +09:00
Andrey Nering
814f350b6d go mod vendor 2020-04-25 15:56:41 -03:00
Andrey Nering
05db8ce582 Merge pull request #315 from go-task/mvdan-sh-3.1.0
Upgrade mvdan.cc/sh to v3.1.0
2020-04-25 15:55:32 -03:00
Andrey Nering
3fd36a0c72 Upgrade mvdan.cc/sh to v3.1.0
Closes #270
2020-04-25 15:51:47 -03:00
Andrey Nering
d52d74c64c go mod vendor 2020-03-22 21:42:45 -03:00
Andrey Nering
d36f73de01 Merge pull request #303 from go-task/ci-updates
Remove Travis CI and upgrade Go version on GitHub Actions
2020-03-01 15:49:25 -03:00
Andrey Nering
628c4a7b5f Upgrade Go version on CI 2020-03-01 15:46:56 -03:00
Andrey Nering
ca07a663e1 Remove Travis CI 2020-03-01 15:45:51 -03:00
Andrey Nering
66d008391e Merge pull request #302 from go-task/upgrade-mvdan-sh-to-v3.0.2
Upgrade mvdan.cc/sh to v3.0.2
2020-03-01 15:38:03 -03:00
Andrey Nering
eef84bda26 Upgrade mvdan.cc/sh to v3.0.2 2020-03-01 15:35:23 -03:00
Andrey Nering
e0defe71aa Merge pull request #298 from thejray/master
Remove trailing colon from task listing
2020-03-01 15:26:37 -03:00
thejray
069257151e Remove trailing colon from task listing 2020-02-19 07:22:37 -05:00
Andrey Nering
347ecc028f Merge pull request #286 from kovetskiy/master
Add note about Arch Linux package
2020-02-11 21:26:41 -03:00
Egor Kovetskiy
94ac60fa09 docs/installation.md: fix typo for Git
Co-Authored-By: Andrey Nering <andrey.nering@gmail.com>
2020-02-10 11:45:27 +03:00
Andrey Nering
b08b3546d2 Merge pull request #283 from paulvarache/desc-tmpl
Compile tasks before printing help or summary
2020-01-26 18:47:15 -03:00
Paul Varache
7453e688fd Compile tasks before printing help or summary (Closes #276) 2020-01-26 21:32:20 +00:00
Andrey Nering
32b097b3f2 Merge pull request #281 from paulvarache/ps-complete
Add PowerShell completion script
2020-01-26 17:16:57 -03:00
Egor Kovetskiy
22394def78 Add note about Arch Linux package 2020-01-25 15:44:55 +03:00
Paul Varache
68ecb7fbdd Add PowerShell completion script 2020-01-20 11:26:15 +00:00
Andrey Nering
de98a53b43 Upgrade mvdan.cc/sh to v3.0.1 2020-01-11 21:46:57 -03:00
Andrey Nering
1c9fbf92c6 GitHub Actions: Add action to run GoReleaser on new tags 2020-01-11 21:29:04 -03:00
Andrey Nering
c068b05232 Delete taskfile.org -> taskfile.dev redirect code
This has been migrated to Netlify
2019-12-23 22:25:19 -03:00
Andrey Nering
01e9a8f720 v2.8.0 2019-12-07 21:54:10 -03:00
Andrey Nering
4bdfe64afb Add hability silent all tasks
By add `silent: true` at the root of the Taskfile.
2019-12-07 21:44:09 -03:00
Andrey Nering
ec934ba3c0 .editorconfig: Remove "indent_size"
This way, everyone can configure use their preferred tab size.

Closes #269

Co-authored-by: Nick Klauer <klauer@gmail.com>
2019-12-07 19:49:55 -03:00
Andrey Nering
48add0f293 Write more args tests 2019-12-07 16:48:23 -03:00
Andrey Nering
a4685229c9 Fix bug of Task not executing the "default" task
When global vars were informed using the CLI.

I took the oportunity to move this logic to the proper package and
write a test.
2019-12-07 16:20:36 -03:00
Andrey Nering
f0bc4d26a0 Update FUNDING.yml 2019-11-30 16:15:59 -03:00
Andrey Nering
6a4f420187 go mod vendor 2019-11-24 21:00:02 -03:00
Andrey Nering
6640632683 Merge pull request #271 from go-task/upgrade-mvdan-sh-to-v3.0.0-beta1
Upgrade mvdan.cc/sh to v3.0.0-beta1
2019-11-24 19:20:59 -03:00
Andrey Nering
09d5d802d0 Upgrade mvdan.cc/sh to v3.0.0-beta1 2019-11-24 19:17:09 -03:00
Andrey Nering
fea23ed6d4 Add Changelog and Docs for --parallel 2019-11-15 23:31:18 -03:00
Andrey Nering
10a6c4dc7a Merge pull request #266 from RossHammer/master
Add flag to allow tasks provided on the command line to be run in parallel
2019-11-15 23:22:53 -03:00
Andrey Nering
4cdaa72224 Merge pull request #263 from tillhoff/patch-1
fixed grammar on styleguide
2019-11-15 22:45:07 -03:00
Ross Hammermeister
27bc1ca5d1 Add flag to allow tasks provided on the command line to be run in parallel 2019-11-13 13:50:04 -07:00
till.hoffmann
1ea49188c9 fixed grammar on styleguide 2019-11-13 12:34:13 +01:00
Andrey Nering
3084ef129c v2.7.1 2019-11-10 20:36:17 -03:00
Andrey Nering
c0d112f858 Merge pull request #261 from AlbyIanna/AlbyIanna/fix-typo
fix typo in usage.md
2019-11-10 19:58:06 -03:00
Andrey Nering
2265dda84c Merge pull request #249 from bfarayev/feature/bash-autocomplete
Bash autocompletion for task
2019-11-10 19:53:33 -03:00
Alberto Iannaccone
263b094cab fix typo in usage.md 2019-11-08 11:01:57 +01:00
Bakhtiyar Farayev
fbd13614a5 Fix typo and re-organize the folder structure for task completion 2019-11-05 10:30:01 +11:00
Andrey Nering
0494d7ebe3 Update changelog 2019-10-27 18:27:47 -03:00
Andrey Nering
9a8442c946 Update some tools and fix error and calling exit 0
Fixes #251
2019-10-27 18:14:22 -03:00
Andrey Nering
e1dcd0b441 Add a styleguide to documentation site 2019-10-27 17:28:12 -03:00
Andrey Nering
a152db7054 Docs: Mention GitHub Action by the Arduino team 2019-10-24 23:55:21 -03:00
Andrey Nering
b9e092674e Docs: Advice using Go Modules instead of GOPATH 2019-10-24 23:46:29 -03:00
Andrey Nering
4162b5f41d Merge pull request #248 from go-task/improve-github-actions
Improve GitHub Action and also test Go 1.12
2019-10-24 23:30:21 -03:00
Andrey Nering
67ae6f210f Improve GitHub Action and also test Go 1.12 2019-10-24 23:25:06 -03:00
Andrey Nering
f6c5a46626 Update vendor/ directory
Fixes #250
2019-09-26 19:04:13 -03:00
Andrey Nering
d6f7e01c53 Fix Travis 2019-09-22 18:57:42 -03:00
Andrey Nering
46463e4e24 Disabling broken Travis releasing for now
I plan to move this to GitHub Actions. For now, I'll do it manually.
2019-09-22 18:50:16 -03:00
Andrey Nering
5c420f3a34 v2.7.0 2019-09-22 18:21:31 -03:00
Bakhtiyar Farayev
393712ead2 Add initial version of bash autocomplete 2019-09-15 09:06:00 +10:00
Andrey Nering
84da80356d Use stdlib instead of go-homedir 2019-09-08 22:07:48 -03:00
Andrey Nering
bcbb85eac3 Merge pull request #245 from go-task/upgrade-sh
Upgrade mvdan.cc/sh to use edge
2019-09-08 21:59:59 -03:00
Andrey Nering
0e1d8a72e6 Revert "Ensure the $HOME env is being set on Windows"
This reverts commit 52028fc3bc.
2019-09-08 21:56:23 -03:00
Andrey Nering
bbdd698869 Upgrade mvdan.cc/sh to use edge 2019-09-08 21:55:02 -03:00
Andrey Nering
8f684ffa6d Merge pull request #239 from go-task/ci-using-github-actions
Add CI for Linux/Windows/MacOS powered by GitHub Actions
2019-09-07 14:43:00 -03:00
Andrey Nering
9be3666fe7 Trying to fix Travis 2019-09-07 14:40:39 -03:00
Andrey Nering
b7785678f4 CI: Upgrade to Go 1.13 2019-09-07 14:35:48 -03:00
Andrey Nering
d8005b4cf6 Fix typo 2019-09-07 14:32:02 -03:00
Andrey Nering
52028fc3bc Ensure the $HOME env is being set on Windows 2019-09-07 14:29:13 -03:00
Andrey Nering
5285ec23ae Fix summary test on Windows 2019-09-01 22:26:53 -03:00
Andrey Nering
3c882e5c57 Merge branch 'master' into ci-using-github-actions 2019-09-01 22:18:58 -03:00
Andrey Nering
ad569a8a36 Update CHANGELOG 2019-08-25 16:41:54 -03:00
Andrey Nering
0d9fdbaac1 Small improvements to #228 2019-08-25 16:32:25 -03:00
Andrey Nering
f5cd3eab9e Merge pull request #228 from topecongiro/checksum-look-for-generated
Re-run the task if generated files do not exist
2019-08-25 16:32:03 -03:00
Seiichi Uchida
8987cd64a0 Fix a typo 2019-08-21 13:42:19 +09:00
Seiichi Uchida
fac51dcf03 Fix Checksum.IsUpToDate
- Check whether generates exist after the creation of checksum file
- Check whether generates exist if only the user specified generates fields
- Check for each generates field instead of taking it as a whole
2019-08-21 13:35:16 +09:00
Seiichi Uchida
01101a4c9b Remove directory check 2019-08-21 13:34:58 +09:00
Seiichi Uchida
d561e40817 Update glob.go
- Rename glob() to globs()
- Add glob() which handles a single glob pattern
- Change glob() and globs() so that they do not return directoreis
2019-08-21 13:33:12 +09:00
Seiichi Uchida
0cb298ebdf Separate error handlings for readability 2019-08-19 13:00:10 +09:00
Andrey Nering
a149368725 Calling Go directly on Windows 2019-08-15 22:50:28 -03:00
Andrey Nering
afeefe8259 Build on the root directory 2019-08-15 22:45:46 -03:00
Andrey Nering
690d3c27a2 Do we need to use backslash here? 2019-08-15 22:42:06 -03:00
Andrey Nering
3d56ea5ce5 Fix binary calling on Windows 2019-08-15 22:38:36 -03:00
Andrey Nering
fdff7f80a3 Skip linting for now 2019-08-15 22:35:29 -03:00
Andrey Nering
fe6978b107 Fix CI 2019-08-15 22:32:45 -03:00
Andrey Nering
57db6865d2 Build binary first and test all packages 2019-08-15 22:28:55 -03:00
Andrey Nering
d235d5ab28 Add CI for Linux/Windows/MacOS powered by GitHub Actions 2019-08-15 22:24:31 -03:00
Andrey Nering
613dfe06d3 Fix two Goreleaser deprecation messages
https://goreleaser.com/deprecations/#archive

https://goreleaser.com/deprecations/#nfpm
2019-08-11 23:15:08 -03:00
Andrey Nering
a312d61d68 Update CHANGELOG.md 2019-08-11 23:01:25 -03:00
Andrey Nering
e414c1f7b0 Documentation: Improve wording on the Variables section
Thanks @crewjam for the suggestion

Closes #234
2019-08-10 19:50:47 -03:00
Andrey Nering
955359b073 Fix nil panic bug when assigning global var and no var is declared on the Taskfile
Closes #229
Ref #234
2019-08-10 19:38:57 -03:00
Seiichi Uchida
26e0c0887a Re-run the task if generated files do not exist 2019-08-01 13:08:53 +09:00
Andrey Nering
4c295b564a Update CHANGELOG.md 2019-07-21 11:23:49 -03:00
Andrey Nering
2eb52da0db v2.6.0 2019-07-21 11:11:30 -03:00
Andrey Nering
d8bfb3ab13 Add CHANGELOG and documentation for Linux support on Homebrew
Ref: https://github.com/go-task/homebrew-tap/pull/1

Thanks @dawidd6
2019-07-21 11:03:22 -03:00
Andrey Nering
d970e93507 Add --taskfile flag (alias -t) to allow running another Taskfile
Closes #221
2019-07-21 10:57:04 -03:00
Andrey Nering
762714de68 Merge pull request #213 from marco-m/document-dir-creation
Document dir: creation (see PR #211)
2019-06-16 11:03:08 -03:00
Marco Molteni
82a3651a18 Document dir: creation (see PR #211) 2019-06-16 11:33:00 +02:00
Andrey Nering
abe0352de9 Fixed some bugs regarding minor version checks on version:
1. I have forgot to update it on recent releases. Seems that most people just
   use round versions since nobody complained.
2. It's too hard to understand how the github.com/Masterminds/semver package
   works, so I just got rid of it and we're now using plain float checks.
2019-06-15 22:39:35 -03:00
Andrey Nering
4cee4aa5a8 Fix typo 2019-06-15 21:58:37 -03:00
Andrey Nering
9c68c7c50b Add changelog for #205 2019-06-15 21:56:34 -03:00
Andrey Nering
0608782cfa Merge pull request #205 from CypherpunkArmory/add-precondition-to-task
Add Preconditions to Tasks
2019-06-15 21:55:20 -03:00
Andrey Nering
edeaf3794a Merge pull request #212 from ezhukov/patch-1
Add missing "-" in usage.md
2019-06-15 21:21:41 -03:00
Andrey Nering
fe2b8c8afa Post-fixes to #211 2019-06-15 21:12:54 -03:00
Andrey Nering
b66bf58064 Merge branch 'marco-m-209-create-dir' 2019-06-15 20:53:34 -03:00
Andrey Nering
957dfa9cdf Merge branch '209-create-dir' of https://github.com/marco-m/task into marco-m-209-create-dir 2019-06-15 20:52:08 -03:00
Stephen Prater
cc9264854e Change error output 2019-06-11 12:20:56 -07:00
Stephen Prater
d1463b3e24 Fix typos per review 2019-06-11 11:46:22 -07:00
Eugene Zhukov
f1082520e1 Add missing "-" in usage.md 2019-06-11 11:35:10 +03:00
Marco Molteni
733c563194 Protect creation of "dir:" with a mutex 2019-06-10 17:40:20 +02:00
Andrey Nering
0200d043c3 Add funding button via OpenCollective 2019-06-09 21:53:55 -03:00
Marco Molteni
9c475c36e7 Handle the common case when the task directory is not specified
Closes #209
2019-06-06 20:40:31 +02:00
Marco Molteni
c663c5c507 When "dir:" attribute points to a non-existing dir, create it
Closes #209
2019-06-04 18:58:22 +02:00
Marco Molteni
1e93c38307 Task directory: test when "dir:" attribute points to an existing dir 2019-06-04 18:36:35 +02:00
Marco Molteni
81baf808c9 Task directory: test default case (no "dir:" attribute) 2019-06-04 18:24:01 +02:00
Marco Molteni
74537689dc Fix spelling 2019-06-04 08:08:25 +02:00
Stephen Prater
12ab01d5e6 Clarify difference between status and precondition in docs 2019-05-28 13:18:06 -07:00
Stephen Prater
044d3a0ff9 Remove ignore_errors 2019-05-28 13:02:59 -07:00
Stephen Prater
659cae6a4c Apply suggestions from code review
Co-Authored-By: Andrey Nering <andrey.nering@gmail.com>
2019-05-28 12:28:29 -07:00
Stephen Prater
bd5882f0f0 Add Preconditions to Tasks 2019-05-17 13:51:15 -07:00
432 changed files with 120524 additions and 45610 deletions

View File

@@ -7,7 +7,6 @@ insert_final_newline = true
charset = utf-8
trim_trailing_whitespace = true
indent_style = tab
indent_size = 8
[*.{md,yml,yaml,json,toml,htm,html}]
indent_style = space

2
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,2 @@
open_collective: task
patreon: andreynering

26
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,26 @@
name: goreleaser
on:
push:
tags:
- '*'
jobs:
goreleaser:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v1
- name: Set up Go
uses: actions/setup-go@v1
with:
go-version: 1.14.x
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v1
with:
version: latest
args: release --rm-dist
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}

30
.github/workflows/test.yml vendored Normal file
View File

@@ -0,0 +1,30 @@
name: Test
on: [push, pull_request]
jobs:
test:
name: Test
strategy:
matrix:
go-version: [1.13.x, 1.14.x]
platform: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{matrix.platform}}
steps:
- name: Set up Go ${{matrix.go-version}}
uses: actions/setup-go@v1
with:
go-version: ${{matrix.go-version}}
id: go
- name: Check out code into the Go module directory
uses: actions/checkout@v1
- name: Download Go modules
run: go mod download
env:
GOPROXY: https://proxy.golang.org
- name: Build
run: go build -o ./bin/task -v ./cmd/task
- name: Test
run: ./bin/task test

5
.gitignore vendored
View File

@@ -21,3 +21,8 @@ dist/
# intellij idea/goland
.idea/
# exuberant ctags
tags
/bin

View File

@@ -14,12 +14,11 @@ build:
env:
- CGO_ENABLED=0
archive:
name_template: "{{.Binary}}_{{.Os}}_{{.Arch}}"
format_overrides:
- goos: windows
format: zip
archives:
- name_template: "{{.Binary}}_{{.Os}}_{{.Arch}}"
format_overrides:
- goos: windows
format: zip
release:
draft: true
@@ -30,15 +29,15 @@ snapshot:
checksum:
name_template: "task_checksums.txt"
nfpm:
vendor: Task
homepage: https://github.com/go-task/task
maintainer: Andrey Nering <andrey.nering@gmail.com>
description: Simple task runner written in Go
license: MIT
conflicts:
- taskwarrior
formats:
- deb
- rpm
name_template: "{{.ProjectName}}_{{.Os}}_{{.Arch}}"
nfpms:
- vendor: Task
homepage: https://github.com/go-task/task
maintainer: Andrey Nering <andrey.nering@gmail.com>
description: Simple task runner written in Go
license: MIT
conflicts:
- taskwarrior
formats:
- deb
- rpm
file_name_template: "{{.ProjectName}}_{{.Os}}_{{.Arch}}"

View File

@@ -1,22 +0,0 @@
language: go
go:
- 1.11.x
- 1.12.x
addons:
apt:
packages:
- rpm
script:
- go install github.com/go-task/task/cmd/task
- task ci
deploy:
- provider: script
skip_cleanup: true
script: curl -sL http://git.io/goreleaser | bash
on:
tags: true
condition: $TRAVIS_OS_NAME = linux

View File

@@ -1,5 +1,51 @@
# Changelog
## v2.8.1 - 2019-05-20
- Fix error code for the `--help` flag
([#300](https://github.com/go-task/task/issues/300), [#330](https://github.com/go-task/task/pull/330)).
- Print version to stdout instead of stderr
([#299](https://github.com/go-task/task/issues/299), [#329](https://github.com/go-task/task/pull/329)).
- Supress `context` errors when using the `--watch` flag
([#313](https://github.com/go-task/task/issues/313), [#317](https://github.com/go-task/task/pull/317)).
- Support templating on description
([#276](https://github.com/go-task/task/issues/276), [#283](https://github.com/go-task/task/pull/283)).
## v2.8.0 - 2019-12-07
- Add `--parallel` flag (alias `-p`) to run tasks given by the command line in
parallel
([#266](https://github.com/go-task/task/pull/266)).
- Fixed bug where calling the `task` CLI only informing global vars would not
execute the `default` task.
- Add hability to silent all tasks by adding `silent: true` a the root of the
Taskfile.
## v2.7.1 - 2019-11-10
- Fix error being raised when `exit 0` was called
([#251](https://github.com/go-task/task/issues/251)).
## v2.7.0 - 2019-09-22
- Fixed panic bug when assigning a global variable
([#229](https://github.com/go-task/task/issues/229), [#243](https://github.com/go-task/task/issues/234)).
- A task with `method: checksum` will now re-run if generated files are deleted
([#228](https://github.com/go-task/task/pull/228), [#238](https://github.com/go-task/task/issues/238)).
## v2.6.0 - 2019-07-21
- Fixed some bugs regarding minor version checks on `version:`.
- Add `preconditions:` to task
([#205](https://github.com/go-task/task/pull/205)).
- Create directory informed on `dir:` if it doesn't exist
([#209](https://github.com/go-task/task/issues/209), [#211](https://github.com/go-task/task/pull/211)).
- We now have a `--taskfile` flag (alias `-t`), which can be used to run
another Taskfile (other than the default `Taskfile.yml`)
([#221](https://github.com/go-task/task/pull/221)).
- It's now possible to install Task using Homebrew on Linux
([go-task/homebrew-tap#1](https://github.com/go-task/homebrew-tap/pull/1)).
## v2.5.2 - 2019-05-11
- Reverted YAML upgrade due issues with CRLF on Windows

View File

@@ -1,4 +1,5 @@
[![Build Status](https://travis-ci.org/go-task/task.svg?branch=master)](https://travis-ci.org/go-task/task)
![Test](https://github.com/go-task/task/workflows/Test/badge.svg)
![GoReleaser](https://github.com/go-task/task/workflows/goreleaser/badge.svg)
# Task

View File

@@ -1,5 +1,7 @@
version: '2'
# silent: true
includes:
docs: ./docs

View File

@@ -1,421 +0,0 @@
// This small web app is used to redirect from the old taskfile.org domain
// to the new taskfile.dev without breaking CIs that uses cURL to download
// "/install.sh" without the -L flag (which follow redirects).
package main
import (
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/install.sh" {
println("Dumping install.sh")
w.Write(installShContent)
return
}
println("Redirecting to https://taskfile.dev" + r.URL.Path)
w.Header().Set("Location", "https://taskfile.dev"+r.URL.Path)
w.WriteHeader(301)
})
println("Listening :8080")
panic(http.ListenAndServe(":8080", nil))
}
var installShContent = []byte(`#!/bin/sh
set -e
# Code generated by godownloader on 2018-04-07T17:47:38Z. DO NOT EDIT.
#
usage() {
this=$1
cat <<EOF
$this: download go binaries for go-task/task
Usage: $this [-b] bindir [-d] [tag]
-b sets bindir or installation directory, Defaults to ./bin
-d turns on debug logging
[tag] is a tag from
https://github.com/go-task/task/releases
If tag is missing, then the latest will be used.
Generated by godownloader
https://github.com/goreleaser/godownloader
EOF
exit 2
}
parse_args() {
#BINDIR is ./bin unless set be ENV
# over-ridden by flag below
BINDIR=${BINDIR:-./bin}
while getopts "b:dh?" arg; do
case "$arg" in
b) BINDIR="$OPTARG" ;;
d) log_set_priority 10 ;;
h | \?) usage "$0" ;;
esac
done
shift $((OPTIND - 1))
TAG=$1
}
# this function wraps all the destructive operations
# if a curl|bash cuts off the end of the script due to
# network, either nothing will happen or will syntax error
# out preventing half-done work
execute() {
tmpdir=$(mktmpdir)
log_debug "downloading files into ${tmpdir}"
http_download "${tmpdir}/${TARBALL}" "${TARBALL_URL}"
http_download "${tmpdir}/${CHECKSUM}" "${CHECKSUM_URL}"
hash_sha256_verify "${tmpdir}/${TARBALL}" "${tmpdir}/${CHECKSUM}"
srcdir="${tmpdir}"
(cd "${tmpdir}" && untar "${TARBALL}")
install -d "${BINDIR}"
for binexe in "task" ; do
if [ "$OS" = "windows" ]; then
binexe="${binexe}.exe"
fi
install "${srcdir}/${binexe}" "${BINDIR}/"
log_info "installed ${BINDIR}/${binexe}"
done
}
is_supported_platform() {
platform=$1
found=1
case "$platform" in
windows/386) found=0 ;;
windows/amd64) found=0 ;;
darwin/386) found=0 ;;
darwin/amd64) found=0 ;;
linux/386) found=0 ;;
linux/amd64) found=0 ;;
esac
case "$platform" in
darwin/386) found=1 ;;
esac
return $found
}
check_platform() {
if is_supported_platform "$PLATFORM"; then
# optional logging goes here
true
else
log_crit "platform $PLATFORM is not supported. Make sure this script is up-to-date and file request at https://github.com/${PREFIX}/issues/new"
exit 1
fi
}
tag_to_version() {
if [ -z "${TAG}" ]; then
log_info "checking GitHub for latest tag"
else
log_info "checking GitHub for tag '${TAG}'"
fi
REALTAG=$(github_release "$OWNER/$REPO" "${TAG}") && true
if test -z "$REALTAG"; then
log_crit "unable to find '${TAG}' - use 'latest' or see https://github.com/${PREFIX}/releases for details"
exit 1
fi
# if version starts with 'v', remove it
TAG="$REALTAG"
VERSION=${TAG#v}
}
adjust_format() {
# change format (tar.gz or zip) based on ARCH
case ${ARCH} in
windows) FORMAT=zip ;;
esac
true
}
adjust_os() {
# adjust archive name based on OS
true
}
adjust_arch() {
# adjust archive name based on ARCH
true
}
cat /dev/null <<EOF
------------------------------------------------------------------------
https://github.com/client9/shlib - portable posix shell functions
Public domain - http://unlicense.org
https://github.com/client9/shlib/blob/master/LICENSE.md
but credit (and pull requests) appreciated.
------------------------------------------------------------------------
EOF
is_command() {
command -v "$1" >/dev/null
}
echoerr() {
echo "$@" 1>&2
}
log_prefix() {
echo "$0"
}
_logp=6
log_set_priority() {
_logp="$1"
}
log_priority() {
if test -z "$1"; then
echo "$_logp"
return
fi
[ "$1" -le "$_logp" ]
}
log_tag() {
case $1 in
0) echo "emerg" ;;
1) echo "alert" ;;
2) echo "crit" ;;
3) echo "err" ;;
4) echo "warning" ;;
5) echo "notice" ;;
6) echo "info" ;;
7) echo "debug" ;;
*) echo "$1" ;;
esac
}
log_debug() {
log_priority 7 || return 0
echoerr "$(log_prefix)" "$(log_tag 7)" "$@"
}
log_info() {
log_priority 6 || return 0
echoerr "$(log_prefix)" "$(log_tag 6)" "$@"
}
log_err() {
log_priority 3 || return 0
echoerr "$(log_prefix)" "$(log_tag 3)" "$@"
}
log_crit() {
log_priority 2 || return 0
echoerr "$(log_prefix)" "$(log_tag 2)" "$@"
}
uname_os() {
os=$(uname -s | tr '[:upper:]' '[:lower:]')
case "$os" in
msys_nt) os="windows" ;;
esac
echo "$os"
}
uname_arch() {
arch=$(uname -m)
case $arch in
x86_64) arch="amd64" ;;
x86) arch="386" ;;
i686) arch="386" ;;
i386) arch="386" ;;
aarch64) arch="arm64" ;;
armv5*) arch="arm5" ;;
armv6*) arch="arm6" ;;
armv7*) arch="arm7" ;;
esac
echo ${arch}
}
uname_os_check() {
os=$(uname_os)
case "$os" in
darwin) return 0 ;;
dragonfly) return 0 ;;
freebsd) return 0 ;;
linux) return 0 ;;
android) return 0 ;;
nacl) return 0 ;;
netbsd) return 0 ;;
openbsd) return 0 ;;
plan9) return 0 ;;
solaris) return 0 ;;
windows) return 0 ;;
esac
log_crit "uname_os_check '$(uname -s)' got converted to '$os' which is not a GOOS value. Please file bug at https://github.com/client9/shlib"
return 1
}
uname_arch_check() {
arch=$(uname_arch)
case "$arch" in
386) return 0 ;;
amd64) return 0 ;;
arm64) return 0 ;;
armv5) return 0 ;;
armv6) return 0 ;;
armv7) return 0 ;;
ppc64) return 0 ;;
ppc64le) return 0 ;;
mips) return 0 ;;
mipsle) return 0 ;;
mips64) return 0 ;;
mips64le) return 0 ;;
s390x) return 0 ;;
amd64p32) return 0 ;;
esac
log_crit "uname_arch_check '$(uname -m)' got converted to '$arch' which is not a GOARCH value. Please file bug report at https://github.com/client9/shlib"
return 1
}
untar() {
tarball=$1
case "${tarball}" in
*.tar.gz | *.tgz) tar -xzf "${tarball}" ;;
*.tar) tar -xf "${tarball}" ;;
*.zip) unzip "${tarball}" ;;
*)
log_err "untar unknown archive format for ${tarball}"
return 1
;;
esac
}
mktmpdir() {
test -z "$TMPDIR" && TMPDIR="$(mktemp -d)"
mkdir -p "${TMPDIR}"
echo "${TMPDIR}"
}
http_download_curl() {
local_file=$1
source_url=$2
header=$3
if [ -z "$header" ]; then
code=$(curl -w '%{http_code}' -sL -o "$local_file" "$source_url")
else
code=$(curl -w '%{http_code}' -sL -H "$header" -o "$local_file" "$source_url")
fi
if [ "$code" != "200" ]; then
log_debug "http_download_curl received HTTP status $code"
return 1
fi
return 0
}
http_download_wget() {
local_file=$1
source_url=$2
header=$3
if [ -z "$header" ]; then
wget -q -O "$local_file" "$source_url"
else
wget -q --header "$header" -O "$local_file" "$source_url"
fi
}
http_download() {
log_debug "http_download $2"
if is_command curl; then
http_download_curl "$@"
return
elif is_command wget; then
http_download_wget "$@"
return
fi
log_crit "http_download unable to find wget or curl"
return 1
}
http_copy() {
tmp=$(mktemp)
http_download "${tmp}" "$1" "$2" || return 1
body=$(cat "$tmp")
rm -f "${tmp}"
echo "$body"
}
github_release() {
owner_repo=$1
version=$2
test -z "$version" && version="latest"
giturl="https://github.com/${owner_repo}/releases/${version}"
json=$(http_copy "$giturl" "Accept:application/json")
test -z "$json" && return 1
version=$(echo "$json" | tr -s '\n' ' ' | sed 's/.*"tag_name":"//' | sed 's/".*//')
test -z "$version" && return 1
echo "$version"
}
hash_sha256() {
TARGET=${1:-/dev/stdin}
if is_command gsha256sum; then
hash=$(gsha256sum "$TARGET") || return 1
echo "$hash" | cut -d ' ' -f 1
elif is_command sha256sum; then
hash=$(sha256sum "$TARGET") || return 1
echo "$hash" | cut -d ' ' -f 1
elif is_command shasum; then
hash=$(shasum -a 256 "$TARGET" 2>/dev/null) || return 1
echo "$hash" | cut -d ' ' -f 1
elif is_command openssl; then
hash=$(openssl -dst openssl dgst -sha256 "$TARGET") || return 1
echo "$hash" | cut -d ' ' -f a
else
log_crit "hash_sha256 unable to find command to compute sha-256 hash"
return 1
fi
}
hash_sha256_verify() {
TARGET=$1
checksums=$2
if [ -z "$checksums" ]; then
log_err "hash_sha256_verify checksum file not specified in arg2"
return 1
fi
BASENAME=${TARGET##*/}
want=$(grep "${BASENAME}" "${checksums}" 2>/dev/null | tr '\t' ' ' | cut -d ' ' -f 1)
if [ -z "$want" ]; then
log_err "hash_sha256_verify unable to find checksum for '${TARGET}' in '${checksums}'"
return 1
fi
got=$(hash_sha256 "$TARGET")
if [ "$want" != "$got" ]; then
log_err "hash_sha256_verify checksum for '$TARGET' did not verify ${want} vs $got"
return 1
fi
}
cat /dev/null <<EOF
------------------------------------------------------------------------
End of functions from https://github.com/client9/shlib
------------------------------------------------------------------------
EOF
PROJECT_NAME="task"
OWNER=go-task
REPO="task"
BINARY=task
FORMAT=tar.gz
OS=$(uname_os)
ARCH=$(uname_arch)
PREFIX="$OWNER/$REPO"
# use in logging routines
log_prefix() {
echo "$PREFIX"
}
PLATFORM="${OS}/${ARCH}"
GITHUB_DOWNLOAD=https://github.com/${OWNER}/${REPO}/releases/download
uname_os_check "$OS"
uname_arch_check "$ARCH"
parse_args "$@"
check_platform
tag_to_version
adjust_format
adjust_os
adjust_arch
log_info "found version: ${VERSION} for ${TAG}/${OS}/${ARCH}"
NAME=${BINARY}_${OS}_${ARCH}
TARBALL=${NAME}.${FORMAT}
TARBALL_URL=${GITHUB_DOWNLOAD}/${TAG}/${TARBALL}
CHECKSUM=task_checksums.txt
CHECKSUM_URL=${GITHUB_DOWNLOAD}/${TAG}/${CHECKSUM}
execute
`)

View File

@@ -2,9 +2,11 @@ package main
import (
"context"
"fmt"
"log"
"os"
"os/signal"
"path/filepath"
"syscall"
"github.com/go-task/task/v2"
@@ -17,7 +19,7 @@ var (
version = "master"
)
const usage = `Usage: task [-ilfwvsd] [--init] [--list] [--force] [--watch] [--verbose] [--silent] [--dir] [--dry] [--summary] [task...]
const usage = `Usage: task [-ilfwvsd] [--init] [--list] [--force] [--watch] [--verbose] [--silent] [--dir] [--taskfile] [--dry] [--summary] [task...]
Runs the specified task(s). Falls back to the "default" task if no task name
was specified, or lists all tasks if an unknown task name was specified.
@@ -48,6 +50,7 @@ func main() {
var (
versionFlag bool
helpFlag bool
init bool
list bool
status bool
@@ -57,11 +60,14 @@ func main() {
silent bool
dry bool
summary bool
parallel bool
dir string
entrypoint string
output string
)
pflag.BoolVar(&versionFlag, "version", false, "show Task version")
pflag.BoolVarP(&helpFlag, "help", "h", false, "shows Task usage")
pflag.BoolVarP(&init, "init", "i", false, "creates a new Taskfile.yml in the current folder")
pflag.BoolVarP(&list, "list", "l", false, "lists tasks with description of current Taskfile")
pflag.BoolVar(&status, "status", false, "exits with non-zero exit code if any of the given tasks is not up-to-date")
@@ -69,14 +75,21 @@ func main() {
pflag.BoolVarP(&watch, "watch", "w", false, "enables watch of the given task")
pflag.BoolVarP(&verbose, "verbose", "v", false, "enables verbose mode")
pflag.BoolVarP(&silent, "silent", "s", false, "disables echoing")
pflag.BoolVarP(&parallel, "parallel", "p", false, "executes tasks provided on command line in parallel")
pflag.BoolVar(&dry, "dry", false, "compiles and prints tasks in the order that they would be run, without executing them")
pflag.BoolVar(&summary, "summary", false, "show summary about a task")
pflag.StringVarP(&dir, "dir", "d", "", "sets directory of execution")
pflag.StringVarP(&entrypoint, "taskfile", "t", "", `choose which Taskfile to run. Defaults to "Taskfile.yml"`)
pflag.StringVarP(&output, "output", "o", "", "sets output style: [interleaved|group|prefixed]")
pflag.Parse()
if versionFlag {
log.Printf("Task version: %s\n", version)
fmt.Printf("Task version: %s\n", version)
return
}
if helpFlag {
pflag.Usage()
return
}
@@ -91,14 +104,27 @@ func main() {
return
}
if dir != "" && entrypoint != "" {
log.Fatal("task: You can't set both --dir and --taskfile")
return
}
if entrypoint != "" {
dir = filepath.Dir(entrypoint)
entrypoint = filepath.Base(entrypoint)
} else {
entrypoint = "Taskfile.yml"
}
e := task.Executor{
Force: force,
Watch: watch,
Verbose: verbose,
Silent: silent,
Dir: dir,
Dry: dry,
Summary: summary,
Force: force,
Watch: watch,
Verbose: verbose,
Silent: silent,
Dir: dir,
Dry: dry,
Entrypoint: entrypoint,
Summary: summary,
Parallel: parallel,
Stdin: os.Stdin,
Stdout: os.Stdout,
@@ -115,13 +141,7 @@ func main() {
return
}
arguments := pflag.Args()
if len(arguments) == 0 {
log.Println("task: No argument given, trying default task")
arguments = []string{"default"}
}
calls, globals := args.Parse(arguments...)
calls, globals := args.Parse(pflag.Args()...)
for name, value := range globals {
e.Taskfile.Vars[name] = value
}

21
completion/bash/task.bash Normal file
View File

@@ -0,0 +1,21 @@
_task_completion()
{
local scripts;
local curr_arg;
# Remove colon from word breaks
COMP_WORDBREAKS=${COMP_WORDBREAKS//:}
scripts=$(task -l | sed '1d' | awk '{ print $2 }' | sed 's/:$//');
curr_arg="${COMP_WORDS[COMP_CWORD]:-"."}"
# Do not accept more than 1 argument
if [ "${#COMP_WORDS[@]}" != "2" ]; then
return
fi
COMPREPLY=($(compgen -c | echo "$scripts" | grep $curr_arg));
}
complete -F _task_completion task

10
completion/ps/task.ps1 Normal file
View File

@@ -0,0 +1,10 @@
$scriptBlock = {
param($commandName, $wordToComplete, $cursorPosition)
$curReg = "task{.exe}? (.*?)$"
$startsWith = $wordToComplete | Select-String $curReg -AllMatches | ForEach-Object { $_.Matches.Groups[1].Value }
$reg = "\* ($startsWith.+?):"
$listOutput = $(task -l)
$listOutput | Select-String $reg -AllMatches | ForEach-Object { $_.Matches.Groups[1].Value + " " }
}
Register-ArgumentCompleter -Native -CommandName task -ScriptBlock $scriptBlock

View File

@@ -5,7 +5,7 @@ function __list() {
local -a scripts
if [ -f Taskfile.yml ]; then
scripts=($(task -l | sed '1d' | sed 's/^\* //' | awk '{ print $1 }' | sed 's/:$//' | sed 's/:/\\:/'))
scripts=($(task -l | sed '1d' | sed 's/^\* //' | awk '{ print $1 }' | sed 's/:$//' | sed 's/:/\\:/g'))
_describe 'script' scripts
fi
}

View File

@@ -1,7 +1,8 @@
- [Installation](installation.md)
- [Usage](usage.md)
- [Styleguide](styleguide.md)
- [Taskfile Versions](taskfile_versions.md)
- [Examples](examples.md)
- [Releasing Task](releasing_task.md)
- [Alternative Task Runners](alternative_task_runners.md)
- [![Github](https://icongram.jgog.in/simple/github.svg?color=808080&size=16)Github](https://github.com/go-task/task)
- [![GitHub](https://icongram.jgog.in/simple/github.svg?color=808080&size=16)GitHub](https://github.com/go-task/task)

View File

@@ -6,25 +6,8 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="description" content="A task runner / simpler Make alternative written in Go">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<link rel="stylesheet" href="//unpkg.com/docsify-themeable/dist/css/theme-simple.css">
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify-themeable/dist/css/theme-simple.css">
<meta name="google-site-verification" content="VGAYkbdmuaciIDGkBe-eAg9yfZg0C6ostgonbGxxOa0" />
<script>
var SeedAndDewConfig = {};
(function() {
SeedAndDewConfig['adClass'] = "snd-ad";
/* * * DON'T EDIT BELOW THIS LINE * * */
SeedAndDewConfig['projectId'] = '16e0aed0-b265-48c9-9eae-0aad56147553';
SeedAndDewConfig['loadStartTime'] = performance.now();
SeedAndDewConfig['apiVersion'] = '2018-05-28'
SeedAndDewConfig['sessionId'] = Math.random().toString(36).substring(2, 15);
var snd = document.createElement('script');
snd.type = 'text/javascript';
snd.async = true;
snd.src = 'https://www.seedanddew.com/static/embed.min.js';
(document.getElementsByTagName('head')[0] ||
document.getElementsByTagName('body')[0]).appendChild(snd);
})();
</script>
</head>
<body>
<div id="app"></div>
@@ -32,7 +15,6 @@
window.$docsify = {
name: 'Task',
repo: 'go-task/task',
ga: 'UA-126286662-1',
themeColor: '#00add8',
loadSidebar: true,
auto2top: true,
@@ -40,10 +22,10 @@
subMaxLevel: 3
}
</script>
<script src="//unpkg.com/docsify/lib/docsify.min.js"></script>
<script src="//unpkg.com/docsify/lib/plugins/ga.min.js"></script>
<script src="//unpkg.com/docsify-themeable"></script>
<script src="//unpkg.com/prismjs/components/prism-bash.min.js"></script>
<script src="//unpkg.com/prismjs/components/prism-yaml.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/docsify/lib/docsify.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/docsify-themeable/dist/js/docsify-themeable.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/docsify-tabs"></script>
<script src="//cdn.jsdelivr.net/npm/prismjs/components/prism-bash.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/prismjs/components/prism-yaml.min.js"></script>
</body>
</html>

View File

@@ -1,31 +1,31 @@
# Installation
## Binary
Task offers many installation methods. Check out the available methods below.
Or you can download the binary from the [releases][releases] page and add to
your $PATH. DEB and RPM packages are also available.
The `task_checksums.txt` file contains the sha256 checksum for each file.
## Package Managers
## Homebrew
<!-- tabs:start -->
If you're on macOS and have [Homebrew][homebrew] installed, getting Task is
as simple as running:
#### **Homebrew**
If you're on macOS or Linux and have [Homebrew][homebrew] installed, getting
Task is as simple as running:
```bash
brew install go-task/tap/go-task
```
## Snap
#### **Snap**
Task is available for [Snapcraft][snapcraft], but keep in mind that your
Task is available in [Snapcraft][snapcraft], but keep in mind that your
Linux distribution should allow classic confinement for Snaps to Task work
right:
```bash
sudo snap install task
sudo snap install task --classic
```
## Scoop
#### **Scoop**
If you're on Windows and have [Scoop][scoop] installed, use `extras` bucket
to install Task like:
@@ -38,41 +38,38 @@ scoop install task
This installation method is community owned. After a new release of Task, it
may take some time until it's available on Scoop.
## Go
#### **AUR**
Task now uses [Go Modules](https://github.com/golang/go/wiki/Modules), which
means you may have trouble compiling it on older Go versions.
If you're on Arch Linux you can install Task from
[AUR](https://aur.archlinux.org/packages/taskfile-git) using your favorite
package manager such as `yay`, `pacaur` or `yaourt`:
For CI environments we recommend using the [Install Script](#install-script)
instead, which is faster and more stable, since it'll just download the latest
released binary, instead of compiling the edge (master branch) version.
Installing in your `$GOPATH`:
```bash
go get -u -v github.com/go-task/task/cmd/task
```cmd
yay -S taskfile-git
```
Installing in another directory:
This installation method is community owned, but since it's `-git` version of
the package, it's always latest available version based on the Git repository.
```bash
git clone https://github.com/go-task/task
cd task
<!-- tabs:end -->
# compiling binary to $GOPATH/bin
go install -v
## Get The Binary
# compiling it to another location
# use -o ./task.exe on Windows
go build -v -o ./task ./cmd/task
```
<!-- tabs:start -->
Both methods requires having the [Go][go] environment properly setup locally.
#### **Binary**
## Install script
You can download the binary from the [releases page on GitHub][releases] and
add to your `$PATH`.
DEB and RPM packages are also available.
The `task_checksums.txt` file contains the SHA-256 checksum for each file.
#### **Install Script**
We also have a [install script][installscript], which is very useful on
scenarios like CIs. Many thanks to [godownloader][godownloader] for allowing
scenarios like CIs. Many thanks to [GoDownloader][godownloader] for allowing
easily generating this script.
```bash
@@ -81,8 +78,54 @@ curl -sL https://taskfile.dev/install.sh | sh
> This method will download the binary on the local `./bin` directory by default.
#### **GitHub Actions**
If you want to install Task in GitHub Actions you can try using
[this action](https://github.com/arduino/actions/tree/master/setup-taskfile)
by the Arduino team:
```yaml
- name: Install Task
uses: Arduino/actions/setup-taskfile@master
```
This installation method is community owned.
<!-- tabs:end -->
## Build From Source
<!-- tabs:start -->
#### **Go Modules**
First, make sure you have [Go][go] properly installed and setup.
Task requires [Go Modules](https://github.com/golang/go/wiki/Modules) and
doesn't officially support installing via `go get` anymore.
Installing in another directory:
```bash
git clone https://github.com/go-task/task
cd task
# Compiling binary to $GOPATH/bin
go install -v ./cmd/task
# Compiling it to another location.
# Use -o ./task.exe on Windows.
go build -v -o ./task ./cmd/task
```
> For CI environments we recommend using the [Install Script](#get-the-binary)
> instead, which is faster and more stable, since it'll just download the latest
> released binary, instead of compiling the edge (master branch) version.
<!-- tabs:end -->
[go]: https://golang.org/
[snapcraft]: https://snapcraft.io/
[snapcraft]: https://snapcraft.io/task
[homebrew]: https://brew.sh/
[installscript]: https://github.com/go-task/task/blob/master/install-task.sh
[releases]: https://github.com/go-task/task/releases

View File

@@ -4,9 +4,9 @@ The release process of Task is done with the help of
[GoReleaser][goreleaser]. You can test the release process locally by calling
the `test-release` task of the Taskfile.
The Travis CI should release automatically when a new
Git tag is pushed to master, either for the artifact uploading (raw executables
and DEB and RPM packages)
[GitHub Actions](https://github.com/go-task/task/actions) should release
artifacts automatically when a new Git tag is pushed to master
(raw executables and DEB and RPM packages).
# Homebrew

213
docs/styleguide.md Normal file
View File

@@ -0,0 +1,213 @@
# Styleguide
This is the official Task styleguide for `Taskfile.yml` files. This guide
contains some basic instructions to keep your Taskfile clean and familiar to
other users.
This contains general guidelines, but don't necessarely need to be strictly
followed. Feel free to disagree and proceed differently in some point if you
need or want to. Also, feel free to open issues or pull requests with
improvements to this guide.
## Use `Taskfile.yml` and not `taskfile.yml`
```yaml
# bad
taskfile.yml
# good
Taskfile.yml
```
This is important especially for Linux users. Windows and macOS have case
insensitive filesystems, so `taskfile.yml` will end up working, even that not
officially supported. On Linux, only `Taskfile.yml` will work, though.
## Use the correct order of keywords
- `version:`
- `includes:`
- Configuration ones, like `output:`, `expansions:` or `silent:`
- `vars:`
- `env:`
- `tasks:`
## Use 2 spaces for indentation
This is the most common convention for YAML files, and Task follows it.
```yaml
# bad
tasks:
foo:
cmds:
- echo 'foo'
# good
tasks:
foo:
cmds:
- echo 'foo'
```
## Separate with spaces the mains sections
```yaml
# bad
version: 2
includes:
docker: ./docker/Taskfile.yml
output: prefixed
expansions: 3
vars:
FOO: bar
env:
BAR: baz
tasks:
# ...
# good
version: 2
includes:
docker: ./docker/Taskfile.yml
output: prefixed
expansions: 3
vars:
FOO: bar
env:
BAR: baz
tasks:
# ...
```
## Add spaces between tasks
```yaml
# bad
version: 2
tasks:
foo:
cmds:
- echo 'foo'
bar:
cmds:
- echo 'bar'
baz:
cmds:
- echo 'baz'
# good
version: 2
tasks:
foo:
cmds:
- echo 'foo'
bar:
cmds:
- echo 'bar'
baz:
cmds:
- echo 'baz'
```
## Use upper-case variable names
```yaml
# bad
version: 2
vars:
binary_name: myapp
tasks:
build:
cmds:
- go build -o {{.binary_name}} .
# good
version: 2
vars:
BINARY_NAME: myapp
tasks:
build:
cmds:
- go build -o {{.BINARY_NAME}} .
```
## Don't wrap vars in spaces when templating
```yaml
# bad
version: 2
tasks:
greet:
cmds:
- echo '{{ .MESSAGE }}'
# good
version: 2
tasks:
greet:
cmds:
- echo '{{.MESSAGE}}'
```
This convention is also used by most people for any Go templating.
## Separate task name words with a dash
```yaml
# bad
version: 2
tasks:
do_something_fancy:
cmds:
- echo 'Do something'
# good
version: 2
tasks:
do-something-fancy:
cmds:
- echo 'Do something'
```
## Use colon for task namespacing
```yaml
# good
version: 2
tasks:
docker:build:
cmds:
- docker ...
docker:run:
cmds:
- docker-compose ...
```
This is also done automatically when using included Taskfiles.

View File

@@ -9,8 +9,8 @@ The Taskfile version follows the Task version. E.g. the change to Taskfile
version `2` means that Task `v2.0.0` should be release to support it.
The `version:` key on Taskfile accepts a semver string, so either `2`, `2.0` or
`2.0.0` is accepted. You you choose to use `2.0` Task will not enable future
`2.1` features, but if you choose to use `2`, than any `2.x.x` features will be
`2.0.0` is accepted. If you choose to use `2.0` Task will not enable future
`2.1` features, but if you choose to use `2`, then any `2.x.x` features will be
available, but not `3.0.0+`.
## Version 1
@@ -33,7 +33,7 @@ The variable priority order was also different:
## Version 2.0
At version 2, we introduced the `version:` key, to allow us to envolve Task
At version 2, we introduced the `version:` key, to allow us to evolve Task
with new features without breaking existing Taskfiles. The new syntax is as
follows:
@@ -108,7 +108,7 @@ tasks:
prefix: server
```
From this version it's not also possible to ignore errors of a command or task
From this version it's also possible to ignore errors of a command or task
(check documentation [here][ignore_errors]):
```yaml
@@ -141,6 +141,21 @@ includes:
docker: ./DockerTasks.yml
```
## Version 2.6
Version 2.6 comes with `preconditions` stanza in tasks.
```yaml
version: '2'
tasks:
upload_environment:
preconditions:
- test -f .env
cmds:
- aws s3 cp .env s3://myenvironment
```
Please check the [documentation][includes]
[output]: usage.md#output-syntax

View File

@@ -63,7 +63,7 @@ tasks:
- echo $GREETING
```
> NOTE: `env` supports expansion and and retrieving output from a shell command
> NOTE: `env` supports expansion and retrieving output from a shell command
> just like variables, as you can see on the [Variables](#variables) section.
## Operating System specific tasks
@@ -148,8 +148,14 @@ tasks:
- caddy
```
If the directory doesn't exist, `task` creates it.
## Task dependencies
> Dependencies run in parallel, so dependencies of a task shouldn't depend one
> another. If you want to force tasks to run serially take a look at the
> [Calling Another Task](#calling-another-task) section below.
You may have tasks that depend on others. Just pointing them on `deps` will
make them run automatically before running the parent task:
@@ -191,6 +197,9 @@ tasks:
If there is more than one dependency, they always run in parallel for better
performance.
> You can also make the tasks given by the command line run in parallel by
> using the `--parallel` flag (alias `-p`). Example: `task --parallel js css`.
If you want to pass information to dependencies, you can do that the same
manner as you would to [call another task](#calling-another-task):
@@ -344,12 +353,61 @@ up-to-date.
Also, `task --status [tasks]...` will exit with a non-zero exit code if any of
the tasks are not up-to-date.
If you need a certain set of conditions to be _true_ you can use the
`preconditions` stanza. `preconditions` are very similar to `status`
lines except they support `sh` expansion and they SHOULD all return 0.
```yaml
version: '2'
tasks:
generate-files:
cmds:
- mkdir directory
- touch directory/file1.txt
- touch directory/file2.txt
# test existence of files
preconditions:
- test -f .env
- sh: "[ 1 = 0 ]"
msg: "One doesn't equal Zero, Halting"
```
Preconditions can set specific failure messages that can tell
a user what steps to take using the `msg` field.
If a task has a dependency on a sub-task with a precondition, and that
precondition is not met - the calling task will fail. Note that a task
executed with a failing precondition will not run unless `--force` is
given.
Unlike `status` which will skip a task if it is up to date, and continue
executing tasks that depend on it, a `precondition` will fail a task, along
with any other tasks that depend on it.
```yaml
version: '2'
tasks:
task_will_fail:
preconditions:
- sh: "exit 1"
task_will_also_fail:
deps:
- task_will_fail
task_will_still_fail:
cmds:
- task: task_will_fail
- echo "I will not run"
```
## Variables
When doing interpolation of variables, Task will look for the below.
They are listed below in order of importance (e.g. most important first):
- Variables declared locally in the task
- Variables declared in the task definition
- Variables given while calling a task from another.
(See [Calling another task](#calling-another-task) above)
- Variables declared in the `vars:` option in the `Taskfile`
@@ -385,7 +443,7 @@ version: '2'
tasks:
print-var:
cmds:
echo "{{.VAR}}"
- echo "{{.VAR}}"
vars:
VAR: Hello!
```
@@ -550,7 +608,7 @@ would print the following output:
## Display summary of task
Running `task --summary task-name` will show a summary of a task
Running `task --summary task-name` will show a summary of a task.
The following Taskfile:
```yaml
@@ -562,7 +620,7 @@ tasks:
summary: |
Release your project to github
It will build your project before starting the release it.
It will build your project before starting the release.
Please make sure that you have set GITHUB_TOKEN before starting.
cmds:
- your-release-tool
@@ -579,7 +637,7 @@ task: release
Release your project to github
It will build your project before starting the release it.
It will build your project before starting the release.
Please make sure that you have set GITHUB_TOKEN before starting.
dependencies:
@@ -620,7 +678,7 @@ With silent mode on, the below will be print instead:
Print something
```
There's three ways to enable silent mode:
There are four ways to enable silent mode:
* At command level:
@@ -646,6 +704,19 @@ tasks:
silent: true
```
* Globally at Taskfile level:
```yaml
version: '2'
silent: true
tasks:
echo:
cmds:
- echo "Print something"
```
* Or globally with `--silent` or `-s` flag
If you want to suppress STDOUT instead, just redirect a command to `/dev/null`:

18
go.mod
View File

@@ -1,23 +1,21 @@
module github.com/go-task/task/v2
require (
github.com/Masterminds/semver v1.4.2
github.com/Masterminds/semver v1.4.2 // indirect
github.com/Masterminds/sprig v2.16.0+incompatible
github.com/aokoli/goutils v1.0.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/google/uuid v1.0.0 // indirect
github.com/huandu/xstrings v1.1.0 // indirect
github.com/imdario/mergo v0.3.6 // indirect
github.com/kr/pretty v0.1.0 // indirect
github.com/mattn/go-zglob v0.0.1
github.com/mitchellh/go-homedir v1.0.0
github.com/radovskyb/watcher v1.0.5
github.com/spf13/pflag v1.0.3
github.com/stretchr/testify v1.3.0
golang.org/x/crypto v0.0.0-20180830192347-182538f80094 // indirect
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d // indirect
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f
golang.org/x/sys v0.0.0-20180831094639-fa5fdf94c789 // indirect
gopkg.in/yaml.v2 v2.2.1
mvdan.cc/sh v2.6.4+incompatible
github.com/stretchr/testify v1.4.0
golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc // indirect
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e
gopkg.in/yaml.v2 v2.2.2
mvdan.cc/sh/v3 v3.1.1
)
go 1.13

54
go.sum
View File

@@ -4,9 +4,12 @@ github.com/Masterminds/sprig v2.16.0+incompatible h1:QZbMUPxRQ50EKAq3LFMnxddMu88
github.com/Masterminds/sprig v2.16.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
github.com/aokoli/goutils v1.0.1 h1:7fpzNGoJ3VA8qcrm++XEE1QUe0mIwNeLa02Nwq7RDkg=
github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ=
github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/huandu/xstrings v1.1.0 h1:9oZY6Z/H3A1gytJxzuicbmV5QoR8M1TAPcn9WTg7vqg=
@@ -15,33 +18,52 @@ github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28=
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mattn/go-zglob v0.0.1 h1:xsEx/XUoVlI6yXjqBK062zYhRTZltCNmYPx6v+8DNaY=
github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo=
github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/pkg/diff v0.0.0-20190930165518-531926345625/go.mod h1:kFj35MyHn14a6pIgWhm46KVjJr5CHys3eEYxkuKD1EI=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/radovskyb/watcher v1.0.5 h1:wqt7gb+HjGacvFoLTKeT44C+XVPxu7bvHvKT1IvZ7rw=
github.com/radovskyb/watcher v1.0.5/go.mod h1:78okwvY5wPdzcb1UYnip1pvrZNIVEIh/Cm+ZuvsUYIg=
github.com/rogpeppe/go-internal v1.5.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
golang.org/x/crypto v0.0.0-20180830192347-182538f80094 h1:rVTAlhYa4+lCfNxmAIEOGQRoD23UqP72M3+rSWVGDTg=
golang.org/x/crypto v0.0.0-20180830192347-182538f80094/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d h1:g9qWBGx4puODJTMVyoPrpoxPFgVGd+z1DZwjfRu4d0I=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180831094639-fa5fdf94c789 h1:T8D7l6WB3tLu+VpKvw06ieD/OhBi1XpJmG1U/FtttZg=
golang.org/x/sys v0.0.0-20180831094639-fa5fdf94c789/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc h1:c0o/qxkaO2LF5t6fQrT4b5hzyggAkLLlCUjqfRxd8Q4=
golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200217220822-9197077df867 h1:JoRuNIf+rpHl+VhScRQQvzbHed86tKkqwPMV34T8myw=
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20191110171634-ad39bd3f0407 h1:5zh5atpUEdIc478E/ebrIaHLKcfVvG6dL/fGv7BcMoM=
golang.org/x/term v0.0.0-20191110171634-ad39bd3f0407/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
mvdan.cc/sh v2.6.4+incompatible h1:eD6tDeh0pw+/TOTI1BBEryZ02rD2nMcFsgcvde7jffM=
mvdan.cc/sh v2.6.4+incompatible/go.mod h1:IeeQbZq+x2SUGBensq/jge5lLQbS3XT2ktyp3wrt4x8=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
mvdan.cc/editorconfig v0.1.1-0.20200121172147-e40951bde157/go.mod h1:Ge4atmRUYqueGppvJ7JNrtqpqokoJEFxYbP0Z+WeKS8=
mvdan.cc/sh/v3 v3.1.1 h1:niuYC5Ug0KzLuN6CNX3ru37v4MkVD5Wm9T4Mk2eJr9A=
mvdan.cc/sh/v3 v3.1.1/go.mod h1:F+Vm4ZxPJxDKExMLhvjuI50oPnedVXpfjNSrusiTOno=

View File

@@ -29,6 +29,10 @@ func (e *Executor) tasksWithDesc() (tasks []*taskfile.Task) {
tasks = make([]*taskfile.Task, 0, len(e.Taskfile.Tasks))
for _, task := range e.Taskfile.Tasks {
if task.Desc != "" {
compiledTask, err := e.CompiledTask(taskfile.Call{Task: task.Task})
if err == nil {
task = compiledTask
}
tasks = append(tasks, task)
}
}

View File

@@ -34,6 +34,10 @@ func Parse(args ...string) ([]taskfile.Call, taskfile.Vars) {
}
}
if len(calls) == 0 {
calls = append(calls, taskfile.Call{Task: "default"})
}
return calls, globals
}

View File

@@ -64,6 +64,28 @@ func TestArgs(t *testing.T) {
"FOO": {Static: "bar"},
},
},
{
Args: nil,
ExpectedCalls: []taskfile.Call{
{Task: "default"},
},
},
{
Args: []string{},
ExpectedCalls: []taskfile.Call{
{Task: "default"},
},
},
{
Args: []string{"FOO=bar", "BAR=baz"},
ExpectedCalls: []taskfile.Call{
{Task: "default"},
},
ExpectedGlobals: taskfile.Vars{
"FOO": {Static: "bar"},
"BAR": {Static: "baz"},
},
},
}
for i, test := range tests {

View File

@@ -0,0 +1,13 @@
package execext
import (
"io"
)
var _ io.ReadWriteCloser = devNull{}
type devNull struct{}
func (devNull) Read(p []byte) (int, error) { return 0, io.EOF }
func (devNull) Write(p []byte) (int, error) { return len(p), nil }
func (devNull) Close() error { return nil }

View File

@@ -8,10 +8,10 @@ import (
"path/filepath"
"strings"
"mvdan.cc/sh/expand"
"mvdan.cc/sh/interp"
"mvdan.cc/sh/shell"
"mvdan.cc/sh/syntax"
"mvdan.cc/sh/v3/expand"
"mvdan.cc/sh/v3/interp"
"mvdan.cc/sh/v3/shell"
"mvdan.cc/sh/v3/syntax"
)
// RunCommandOptions is the options for the RunCommand func
@@ -49,8 +49,12 @@ func RunCommand(ctx context.Context, opts *RunCommandOptions) error {
interp.Dir(opts.Dir),
interp.Env(expand.ListEnviron(environ...)),
interp.Module(interp.DefaultExec),
interp.Module(interp.OpenDevImpls(interp.DefaultOpen)),
interp.OpenHandler(func(ctx context.Context, path string, flag int, perm os.FileMode) (io.ReadWriteCloser, error) {
if path == "/dev/null" {
return devNull{}, nil
}
return interp.DefaultOpenHandler()(ctx, path, flag, perm)
}),
interp.StdIO(opts.Stdin, opts.Stdout, opts.Stderr),
)
@@ -62,12 +66,10 @@ func RunCommand(ctx context.Context, opts *RunCommandOptions) error {
// IsExitError returns true the given error is an exis status error
func IsExitError(err error) bool {
switch err.(type) {
case interp.ExitStatus, interp.ShellExitStatus:
if _, ok := interp.IsExitStatus(err); ok {
return true
default:
return false
}
return false
}
// Expand is a helper to mvdan.cc/shell.Fields that returns the first field

View File

@@ -14,10 +14,11 @@ import (
// Checksum validades if a task is up to date by calculating its source
// files checksum
type Checksum struct {
Dir string
Task string
Sources []string
Dry bool
Dir string
Task string
Sources []string
Generates []string
Dry bool
}
// IsUpToDate implements the Checker interface
@@ -27,7 +28,7 @@ func (c *Checksum) IsUpToDate() (bool, error) {
data, _ := ioutil.ReadFile(checksumFile)
oldMd5 := strings.TrimSpace(string(data))
sources, err := glob(c.Dir, c.Sources)
sources, err := globs(c.Dir, c.Sources)
if err != nil {
return false, err
}
@@ -43,6 +44,23 @@ func (c *Checksum) IsUpToDate() (bool, error) {
return false, err
}
}
if len(c.Generates) > 0 {
// For each specified 'generates' field, check whether the files actually exist
for _, g := range c.Generates {
generates, err := glob(c.Dir, g)
if os.IsNotExist(err) {
return false, nil
}
if err != nil {
return false, err
}
if len(generates) == 0 {
return false, nil
}
}
}
return oldMd5 == newMd5, nil
}
@@ -50,21 +68,14 @@ func (c *Checksum) checksum(files ...string) (string, error) {
h := md5.New()
for _, f := range files {
// also sum the filename, so checksum changes for renaming a file
if _, err := io.Copy(h, strings.NewReader(filepath.Base(f))); err != nil {
return "", err
}
f, err := os.Open(f)
if err != nil {
return "", err
}
info, err := f.Stat()
if err != nil {
return "", err
}
if info.IsDir() {
continue
}
// also sum the filename, so checksum changes for renaming a file
if _, err = io.Copy(h, strings.NewReader(info.Name())); err != nil {
return "", err
}
if _, err = io.Copy(h, f); err != nil {
return "", err
}

View File

@@ -1,6 +1,7 @@
package status
import (
"os"
"path/filepath"
"sort"
@@ -9,21 +10,41 @@ import (
"github.com/mattn/go-zglob"
)
func glob(dir string, globs []string) (files []string, err error) {
func globs(dir string, globs []string) ([]string, error) {
files := make([]string, 0)
for _, g := range globs {
if !filepath.IsAbs(g) {
g = filepath.Join(dir, g)
}
g, err = execext.Expand(g)
if err != nil {
return nil, err
}
f, err := zglob.Glob(g)
f, err := glob(dir, g)
if err != nil {
continue
}
files = append(files, f...)
}
sort.Strings(files)
return
return files, nil
}
func glob(dir string, g string) ([]string, error) {
files := make([]string, 0)
if !filepath.IsAbs(g) {
g = filepath.Join(dir, g)
}
g, err := execext.Expand(g)
if err != nil {
return nil, err
}
fs, err := zglob.Glob(g)
if err != nil {
return nil, err
}
for _, f := range fs {
info, err := os.Stat(f)
if err != nil {
return nil, err
}
if info.IsDir() {
continue
}
files = append(files, f)
}
return files, nil
}

View File

@@ -19,11 +19,11 @@ func (t *Timestamp) IsUpToDate() (bool, error) {
return false, nil
}
sources, err := glob(t.Dir, t.Sources)
sources, err := globs(t.Dir, t.Sources)
if err != nil {
return false, nil
}
generates, err := glob(t.Dir, t.Generates)
generates, err := globs(t.Dir, t.Generates)
if err != nil {
return false, nil
}

View File

@@ -9,12 +9,12 @@ import (
func PrintTasks(l *logger.Logger, t *taskfile.Taskfile, c []taskfile.Call) {
for i, call := range c {
printSpaceBetweenSummaries(l, i)
PrintSpaceBetweenSummaries(l, i)
PrintTask(l, t.Tasks[call.Task])
}
}
func printSpaceBetweenSummaries(l *logger.Logger, i int) {
func PrintSpaceBetweenSummaries(l *logger.Logger, i int) {
spaceRequired := i > 0
if !spaceRequired {
return

View File

@@ -0,0 +1,45 @@
package taskfile
import (
"errors"
"fmt"
)
var (
// ErrCantUnmarshalPrecondition is returned for invalid precond YAML.
ErrCantUnmarshalPrecondition = errors.New("task: Can't unmarshal precondition value")
)
// Precondition represents a precondition necessary for a task to run
type Precondition struct {
Sh string
Msg string
}
// UnmarshalYAML implements yaml.Unmarshaler interface.
func (p *Precondition) UnmarshalYAML(unmarshal func(interface{}) error) error {
var cmd string
if err := unmarshal(&cmd); err == nil {
p.Sh = cmd
p.Msg = fmt.Sprintf("`%s` failed", cmd)
return nil
}
var sh struct {
Sh string
Msg string
}
if err := unmarshal(&sh); err != nil {
return err
}
p.Sh = sh.Sh
p.Msg = sh.Msg
if p.Msg == "" {
p.Msg = fmt.Sprintf("%s failed", sh.Sh)
}
return nil
}

View File

@@ -0,0 +1,48 @@
package taskfile_test
import (
"testing"
"github.com/go-task/task/v2/internal/taskfile"
"github.com/stretchr/testify/assert"
"gopkg.in/yaml.v2"
)
func TestPreconditionParse(t *testing.T) {
tests := []struct {
content string
v interface{}
expected interface{}
}{
{
"test -f foo.txt",
&taskfile.Precondition{},
&taskfile.Precondition{Sh: `test -f foo.txt`, Msg: "`test -f foo.txt` failed"},
},
{
"sh: '[ 1 = 0 ]'",
&taskfile.Precondition{},
&taskfile.Precondition{Sh: "[ 1 = 0 ]", Msg: "[ 1 = 0 ] failed"},
},
{`
sh: "[ 1 = 2 ]"
msg: "1 is not 2"
`,
&taskfile.Precondition{},
&taskfile.Precondition{Sh: "[ 1 = 2 ]", Msg: "1 is not 2"},
},
{`
sh: "[ 1 = 2 ]"
msg: "1 is not 2"
`,
&taskfile.Precondition{},
&taskfile.Precondition{Sh: "[ 1 = 2 ]", Msg: "1 is not 2"},
},
}
for _, test := range tests {
err := yaml.Unmarshal([]byte(test.content), test.v)
assert.NoError(t, err)
assert.Equal(t, test.expected, test.v)
}
}

View File

@@ -15,16 +15,13 @@ import (
var (
// ErrIncludedTaskfilesCantHaveIncludes is returned when a included Taskfile contains includes
ErrIncludedTaskfilesCantHaveIncludes = errors.New("task: Included Taskfiles can't have includes. Please, move the include to the main Taskfile")
// ErrNoTaskfileFound is returned when Taskfile.yml is not found
ErrNoTaskfileFound = errors.New(`task: No Taskfile.yml found. Use "task --init" to create a new one`)
)
// Taskfile reads a Taskfile for a given directory
func Taskfile(dir string) (*taskfile.Taskfile, error) {
path := filepath.Join(dir, "Taskfile.yml")
func Taskfile(dir string, entrypoint string) (*taskfile.Taskfile, error) {
path := filepath.Join(dir, entrypoint)
if _, err := os.Stat(path); err != nil {
return nil, ErrNoTaskfileFound
return nil, fmt.Errorf(`task: No Taskfile found on "%s". Use "task --init" to create a new one`, path)
}
t, err := readTaskfile(path)
if err != nil {

View File

@@ -5,19 +5,20 @@ type Tasks map[string]*Task
// Task represents a task
type Task struct {
Task string
Cmds []*Cmd
Deps []*Dep
Desc string
Summary string
Sources []string
Generates []string
Status []string
Dir string
Vars Vars
Env Vars
Silent bool
Method string
Prefix string
IgnoreError bool `yaml:"ignore_error"`
Task string
Cmds []*Cmd
Deps []*Dep
Desc string
Summary string
Sources []string
Generates []string
Status []string
Preconditions []*Precondition
Dir string
Vars Vars
Env Vars
Silent bool
Method string
Prefix string
IgnoreError bool `yaml:"ignore_error"`
}

View File

@@ -9,6 +9,7 @@ type Taskfile struct {
Vars Vars
Env Vars
Tasks Tasks
Silent bool
}
// UnmarshalYAML implements yaml.Unmarshaler interface
@@ -26,6 +27,7 @@ func (tf *Taskfile) UnmarshalYAML(unmarshal func(interface{}) error) error {
Vars Vars
Env Vars
Tasks Tasks
Silent bool
}
if err := unmarshal(&taskfile); err != nil {
return err
@@ -37,8 +39,12 @@ func (tf *Taskfile) UnmarshalYAML(unmarshal func(interface{}) error) error {
tf.Vars = taskfile.Vars
tf.Env = taskfile.Env
tf.Tasks = taskfile.Tasks
tf.Silent = taskfile.Silent
if tf.Expansions <= 0 {
tf.Expansions = 2
}
if tf.Vars == nil {
tf.Vars = make(Vars)
}
return nil
}

View File

@@ -1,46 +0,0 @@
package version
import (
"github.com/Masterminds/semver"
)
var (
v1 = mustVersion("1")
v2 = mustVersion("2")
v21 = mustVersion("2.1")
v22 = mustVersion("2.2")
v23 = mustVersion("2.3")
)
// IsV1 returns if is a given Taskfile version is version 1
func IsV1(v *semver.Constraints) bool {
return v.Check(v1)
}
// IsV2 returns if is a given Taskfile version is at least version 2
func IsV2(v *semver.Constraints) bool {
return v.Check(v2)
}
// IsV21 returns if is a given Taskfile version is at least version 2.1
func IsV21(v *semver.Constraints) bool {
return v.Check(v21)
}
// IsV22 returns if is a given Taskfile version is at least version 2.2
func IsV22(v *semver.Constraints) bool {
return v.Check(v22)
}
// IsV23 returns if is a given Taskfile version is at least version 2.3
func IsV23(v *semver.Constraints) bool {
return v.Check(v23)
}
func mustVersion(s string) *semver.Version {
v, err := semver.NewVersion(s)
if err != nil {
panic(err)
}
return v
}

31
precondition.go Normal file
View File

@@ -0,0 +1,31 @@
package task
import (
"context"
"errors"
"github.com/go-task/task/v2/internal/execext"
"github.com/go-task/task/v2/internal/taskfile"
)
var (
// ErrPreconditionFailed is returned when a precondition fails
ErrPreconditionFailed = errors.New("task: precondition not met")
)
func (e *Executor) areTaskPreconditionsMet(ctx context.Context, t *taskfile.Task) (bool, error) {
for _, p := range t.Preconditions {
err := execext.RunCommand(ctx, &execext.RunCommandOptions{
Command: p.Sh,
Dir: t.Dir,
Env: getEnviron(t),
})
if err != nil {
e.Logger.Errf("task: %s", p.Msg)
return false, ErrPreconditionFailed
}
}
return true, nil
}

View File

@@ -58,10 +58,11 @@ func (e *Executor) getStatusChecker(t *taskfile.Task) (status.Checker, error) {
}, nil
case "checksum":
return &status.Checksum{
Dir: t.Dir,
Task: t.Task,
Sources: t.Sources,
Dry: e.Dry,
Dir: t.Dir,
Task: t.Task,
Sources: t.Sources,
Generates: t.Generates,
Dry: e.Dry,
}, nil
case "none":
return status.None{}, nil
@@ -78,8 +79,10 @@ func (e *Executor) isTaskUpToDateStatus(ctx context.Context, t *taskfile.Task) (
Env: getEnviron(t),
})
if err != nil {
e.Logger.VerboseOutf("task: status command %s exited non-zero: %s", s, err)
return false, nil
}
e.Logger.VerboseOutf("task: status command %s exited zero", s)
}
return true, nil
}

141
task.go
View File

@@ -2,9 +2,12 @@ package task
import (
"context"
"errors"
"fmt"
"io"
"os"
"strconv"
"sync"
"sync/atomic"
"github.com/go-task/task/v2/internal/compiler"
@@ -16,9 +19,7 @@ import (
"github.com/go-task/task/v2/internal/summary"
"github.com/go-task/task/v2/internal/taskfile"
"github.com/go-task/task/v2/internal/taskfile/read"
"github.com/go-task/task/v2/internal/taskfile/version"
"github.com/Masterminds/semver"
"golang.org/x/sync/errgroup"
)
@@ -31,13 +32,16 @@ const (
// Executor executes a Taskfile
type Executor struct {
Taskfile *taskfile.Taskfile
Dir string
Force bool
Watch bool
Verbose bool
Silent bool
Dry bool
Summary bool
Dir string
Entrypoint string
Force bool
Watch bool
Verbose bool
Silent bool
Dry bool
Summary bool
Parallel bool
Stdin io.Reader
Stdout io.Writer
@@ -51,6 +55,7 @@ type Executor struct {
taskvars taskfile.Vars
taskCallCount map[string]*int32
mkdirMutexMap map[string]*sync.Mutex
}
// Run runs Task
@@ -65,7 +70,14 @@ func (e *Executor) Run(ctx context.Context, calls ...taskfile.Call) error {
}
if e.Summary {
summary.PrintTasks(e.Logger, e.Taskfile, calls)
for i, c := range calls {
compiledTask, err := e.CompiledTask(c)
if err != nil {
return nil
}
summary.PrintSpaceBetweenSummaries(e.Logger, i)
summary.PrintTask(e.Logger, compiledTask)
}
return nil
}
@@ -73,18 +85,28 @@ func (e *Executor) Run(ctx context.Context, calls ...taskfile.Call) error {
return e.watchTasks(calls...)
}
g, ctx := errgroup.WithContext(ctx)
for _, c := range calls {
if err := e.RunTask(ctx, c); err != nil {
return err
c := c
if e.Parallel {
g.Go(func() error { return e.RunTask(ctx, c) })
} else {
if err := e.RunTask(ctx, c); err != nil {
return err
}
}
}
return nil
return g.Wait()
}
// Setup setups Executor's internal state
func (e *Executor) Setup() error {
if e.Entrypoint == "" {
e.Entrypoint = "Taskfile.yml"
}
var err error
e.Taskfile, err = read.Taskfile(e.Dir)
e.Taskfile, err = read.Taskfile(e.Dir, e.Entrypoint)
if err != nil {
return err
}
@@ -93,11 +115,6 @@ func (e *Executor) Setup() error {
return err
}
v, err := semver.NewConstraint(e.Taskfile.Version)
if err != nil {
return fmt.Errorf(`task: could not parse taskfile version "%s": %v`, e.Taskfile.Version, err)
}
if e.Stdin == nil {
e.Stdin = os.Stdin
}
@@ -112,14 +129,30 @@ func (e *Executor) Setup() error {
Stderr: e.Stderr,
Verbose: e.Verbose,
}
switch {
case version.IsV1(v):
v, err := strconv.ParseFloat(e.Taskfile.Version, 64)
if err != nil {
return fmt.Errorf(`task: Could not parse taskfile version "%s": %v`, e.Taskfile.Version, err)
}
// consider as equal to the greater version if round
if v == 2.0 {
v = 2.6
}
if v < 1 {
return fmt.Errorf(`task: Taskfile version should be greater or equal to v1`)
}
if v > 2.6 {
return fmt.Errorf(`task: Taskfile versions greater than v2.6 not implemented in the version of Task`)
}
if v < 2 {
e.Compiler = &compilerv1.CompilerV1{
Dir: e.Dir,
Vars: e.taskvars,
Logger: e.Logger,
}
case version.IsV2(v), version.IsV21(v), version.IsV22(v):
} else { // v >= 2
e.Compiler = &compilerv2.CompilerV2{
Dir: e.Dir,
Taskvars: e.taskvars,
@@ -127,16 +160,15 @@ func (e *Executor) Setup() error {
Expansions: e.Taskfile.Expansions,
Logger: e.Logger,
}
case version.IsV23(v):
return fmt.Errorf(`task: Taskfile versions greater than v2.3 not implemented in the version of Task`)
}
if !version.IsV21(v) && e.Taskfile.Output != "" {
if v < 2.1 && e.Taskfile.Output != "" {
return fmt.Errorf(`task: Taskfile option "output" is only available starting on Taskfile version v2.1`)
}
if !version.IsV22(v) && len(e.Taskfile.Includes) > 0 {
if v < 2.2 && len(e.Taskfile.Includes) > 0 {
return fmt.Errorf(`task: Including Taskfiles is only available starting on Taskfile version v2.2`)
}
if e.OutputStyle != "" {
e.Taskfile.Output = e.OutputStyle
}
@@ -151,8 +183,8 @@ func (e *Executor) Setup() error {
return fmt.Errorf(`task: output option "%s" not recognized`, e.Taskfile.Output)
}
if !version.IsV21(v) {
err := fmt.Errorf(`task: Taskfile option "ignore_error" is only available starting on Taskfile version v2.1`)
if v <= 2.1 {
err := errors.New(`task: Taskfile option "ignore_error" is only available starting on Taskfile version v2.1`)
for _, task := range e.Taskfile.Tasks {
if task.IgnoreError {
@@ -166,9 +198,19 @@ func (e *Executor) Setup() error {
}
}
if v < 2.6 {
for _, task := range e.Taskfile.Tasks {
if len(task.Preconditions) > 0 {
return errors.New(`task: Task option "preconditions" is only available starting on Taskfile version v2.6`)
}
}
}
e.taskCallCount = make(map[string]*int32, len(e.Taskfile.Tasks))
e.mkdirMutexMap = make(map[string]*sync.Mutex, len(e.Taskfile.Tasks))
for k := range e.Taskfile.Tasks {
e.taskCallCount[k] = new(int32)
e.mkdirMutexMap[k] = &sync.Mutex{}
}
return nil
}
@@ -188,11 +230,17 @@ func (e *Executor) RunTask(ctx context.Context, call taskfile.Call) error {
}
if !e.Force {
preCondMet, err := e.areTaskPreconditionsMet(ctx, t)
if err != nil {
return err
}
upToDate, err := e.isTaskUpToDate(ctx, t)
if err != nil {
return err
}
if upToDate {
if upToDate && preCondMet {
if !e.Silent {
e.Logger.Errf(`task: Task "%s" is up to date`, t.Task)
}
@@ -200,6 +248,10 @@ func (e *Executor) RunTask(ctx context.Context, call taskfile.Call) error {
}
}
if err := e.mkdir(t); err != nil {
e.Logger.Errf("task: cannot make directory %q: %v", t.Dir, err)
}
for i := range t.Cmds {
if err := e.runCommand(ctx, t, call, i); err != nil {
if err2 := e.statusOnError(t); err2 != nil {
@@ -217,6 +269,23 @@ func (e *Executor) RunTask(ctx context.Context, call taskfile.Call) error {
return nil
}
func (e *Executor) mkdir(t *taskfile.Task) error {
if t.Dir == "" {
return nil
}
mutex := e.mkdirMutexMap[t.Task]
mutex.Lock()
defer mutex.Unlock()
if _, err := os.Stat(t.Dir); os.IsNotExist(err) {
if err := os.MkdirAll(t.Dir, 0755); err != nil {
return err
}
}
return nil
}
func (e *Executor) runDeps(ctx context.Context, t *taskfile.Task) error {
g, ctx := errgroup.WithContext(ctx)
@@ -224,7 +293,11 @@ func (e *Executor) runDeps(ctx context.Context, t *taskfile.Task) error {
d := d
g.Go(func() error {
return e.RunTask(ctx, taskfile.Call{Task: d.Task, Vars: d.Vars})
err := e.RunTask(ctx, taskfile.Call{Task: d.Task, Vars: d.Vars})
if err != nil {
return err
}
return nil
})
}
@@ -236,9 +309,13 @@ func (e *Executor) runCommand(ctx context.Context, t *taskfile.Task, call taskfi
switch {
case cmd.Task != "":
return e.RunTask(ctx, taskfile.Call{Task: cmd.Task, Vars: cmd.Vars})
err := e.RunTask(ctx, taskfile.Call{Task: cmd.Task, Vars: cmd.Vars})
if err != nil {
return err
}
return nil
case cmd.Cmd != "":
if e.Verbose || (!cmd.Silent && !t.Silent && !e.Silent) {
if e.Verbose || (!cmd.Silent && !t.Silent && !e.Taskfile.Silent && !e.Silent) {
e.Logger.Errf(cmd.Cmd)
}

View File

@@ -7,13 +7,13 @@ import (
"io/ioutil"
"os"
"path/filepath"
"runtime"
"strings"
"testing"
"github.com/go-task/task/v2"
"github.com/go-task/task/v2/internal/taskfile"
"github.com/mitchellh/go-homedir"
"github.com/stretchr/testify/assert"
)
@@ -236,7 +236,7 @@ func TestDeps(t *testing.T) {
for _, f := range files {
f = filepath.Join(dir, f)
if _, err := os.Stat(f); err != nil {
t.Errorf("File %s should exists", f)
t.Errorf("File %s should exist", f)
}
}
}
@@ -248,7 +248,7 @@ func TestStatus(t *testing.T) {
_ = os.Remove(file)
if _, err := os.Stat(file); err == nil {
t.Errorf("File should not exists: %v", err)
t.Errorf("File should not exist: %v", err)
}
var buff bytes.Buffer
@@ -262,7 +262,7 @@ func TestStatus(t *testing.T) {
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "gen-foo"}))
if _, err := os.Stat(file); err != nil {
t.Errorf("File should exists: %v", err)
t.Errorf("File should exist: %v", err)
}
e.Silent = false
@@ -273,6 +273,47 @@ func TestStatus(t *testing.T) {
}
}
func TestPrecondition(t *testing.T) {
const dir = "testdata/precondition"
var buff bytes.Buffer
e := &task.Executor{
Dir: dir,
Stdout: &buff,
Stderr: &buff,
}
// A precondition that has been met
assert.NoError(t, e.Setup())
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "foo"}))
if buff.String() != "" {
t.Errorf("Got Output when none was expected: %s", buff.String())
}
// A precondition that was not met
assert.Error(t, e.Run(context.Background(), taskfile.Call{Task: "impossible"}))
if buff.String() != "task: 1 != 0 obviously!\n" {
t.Errorf("Wrong output message: %s", buff.String())
}
buff.Reset()
// Calling a task with a precondition in a dependency fails the task
assert.Error(t, e.Run(context.Background(), taskfile.Call{Task: "depends_on_impossible"}))
if buff.String() != "task: 1 != 0 obviously!\n" {
t.Errorf("Wrong output message: %s", buff.String())
}
buff.Reset()
// Calling a task with a precondition in a cmd fails the task
assert.Error(t, e.Run(context.Background(), taskfile.Call{Task: "executes_failing_task_as_cmd"}))
if buff.String() != "task: 1 != 0 obviously!\n" {
t.Errorf("Wrong output message: %s", buff.String())
}
buff.Reset()
}
func TestGenerates(t *testing.T) {
const (
srcTask = "sub/src.txt"
@@ -290,7 +331,7 @@ func TestGenerates(t *testing.T) {
path := filepath.Join(dir, task)
_ = os.Remove(path)
if _, err := os.Stat(path); err == nil {
t.Errorf("File should not exists: %v", err)
t.Errorf("File should not exist: %v", err)
}
}
@@ -311,10 +352,10 @@ func TestGenerates(t *testing.T) {
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: theTask}))
if _, err := os.Stat(srcFile); err != nil {
t.Errorf("File should exists: %v", err)
t.Errorf("File should exist: %v", err)
}
if _, err := os.Stat(destFile); err != nil {
t.Errorf("File should exists: %v", err)
t.Errorf("File should exist: %v", err)
}
// Ensure task was not incorrectly found to be up-to-date on first run.
if buff.String() == upToDate {
@@ -371,7 +412,7 @@ func TestInit(t *testing.T) {
_ = os.Remove(file)
if _, err := os.Stat(file); err == nil {
t.Errorf("Taskfile.yml should not exists")
t.Errorf("Taskfile.yml should not exist")
}
if err := task.InitTaskfile(ioutil.Discard, dir); err != nil {
@@ -379,7 +420,7 @@ func TestInit(t *testing.T) {
}
if _, err := os.Stat(file); err != nil {
t.Errorf("Taskfile.yml should exists")
t.Errorf("Taskfile.yml should exist")
}
}
@@ -437,7 +478,7 @@ func TestTaskIgnoreErrors(t *testing.T) {
func TestExpand(t *testing.T) {
const dir = "testdata/expand"
home, err := homedir.Dir()
home, err := os.UserHomeDir()
if err != nil {
t.Errorf("Couldn't get $HOME: %v", err)
}
@@ -567,11 +608,76 @@ func TestSummary(t *testing.T) {
}
assert.NoError(t, e.Setup())
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "task-with-summary"}, taskfile.Call{Task: "other-task-with-summary"}))
assert.Equal(t, readTestFixture(t, dir, "task-with-summary.txt"), buff.String())
data, err := ioutil.ReadFile(filepath.Join(dir, "task-with-summary.txt"))
assert.NoError(t, err)
expectedOutput := string(data)
if runtime.GOOS == "windows" {
expectedOutput = strings.Replace(expectedOutput, "\r\n", "\n", -1)
}
assert.Equal(t, expectedOutput, buff.String())
}
func readTestFixture(t *testing.T, dir string, file string) string {
b, err := ioutil.ReadFile(dir + "/" + file)
assert.NoError(t, err, "error reading text fixture")
return string(b)
func TestWhenNoDirAttributeItRunsInSameDirAsTaskfile(t *testing.T) {
const expected = "dir"
const dir = "testdata/" + expected
var out bytes.Buffer
e := &task.Executor{
Dir: dir,
Stdout: &out,
Stderr: &out,
}
assert.NoError(t, e.Setup())
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "whereami"}))
// got should be the "dir" part of "testdata/dir"
got := strings.TrimSuffix(filepath.Base(out.String()), "\n")
assert.Equal(t, expected, got, "Mismatch in the working directory")
}
func TestWhenDirAttributeAndDirExistsItRunsInThatDir(t *testing.T) {
const expected = "exists"
const dir = "testdata/dir/explicit_exists"
var out bytes.Buffer
e := &task.Executor{
Dir: dir,
Stdout: &out,
Stderr: &out,
}
assert.NoError(t, e.Setup())
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "whereami"}))
got := strings.TrimSuffix(filepath.Base(out.String()), "\n")
assert.Equal(t, expected, got, "Mismatch in the working directory")
}
func TestWhenDirAttributeItCreatesMissingAndRunsInThatDir(t *testing.T) {
const expected = "createme"
const dir = "testdata/dir/explicit_doesnt_exist/"
const toBeCreated = dir + expected
const target = "whereami"
var out bytes.Buffer
e := &task.Executor{
Dir: dir,
Stdout: &out,
Stderr: &out,
}
// Ensure that the directory to be created doesn't actually exist.
_ = os.Remove(toBeCreated)
if _, err := os.Stat(toBeCreated); err == nil {
t.Errorf("Directory should not exist: %v", err)
}
assert.NoError(t, e.Setup())
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: target}))
got := strings.TrimSuffix(filepath.Base(out.String()), "\n")
assert.Equal(t, expected, got, "Mismatch in the working directory")
// Clean-up after ourselves only if no error.
_ = os.Remove(toBeCreated)
}

7
testdata/dir/Taskfile.yml vendored Normal file
View File

@@ -0,0 +1,7 @@
version: '2'
tasks:
whereami:
cmds:
- pwd
silent: true

View File

@@ -0,0 +1,8 @@
version: '2'
tasks:
whereami:
dir: createme
cmds:
- pwd
silent: true

View File

@@ -0,0 +1,8 @@
version: '2'
tasks:
whereami:
dir: exists
cmds:
- pwd
silent: true

View File

19
testdata/precondition/Taskfile.yml vendored Normal file
View File

@@ -0,0 +1,19 @@
version: '2'
tasks:
foo:
preconditions:
- test -f foo.txt
impossible:
preconditions:
- sh: "[ 1 = 0 ]"
msg: "1 != 0 obviously!"
depends_on_impossible:
deps:
- impossible
executes_failing_task_as_cmd:
cmds:
- task: impossible

0
testdata/precondition/foo.txt vendored Normal file
View File

View File

@@ -25,6 +25,7 @@ func (e *Executor) CompiledTask(call taskfile.Call) (*taskfile.Task, error) {
new := taskfile.Task{
Task: origTask.Task,
Desc: r.Replace(origTask.Desc),
Summary: r.Replace(origTask.Summary),
Sources: r.ReplaceSlice(origTask.Sources),
Generates: r.ReplaceSlice(origTask.Generates),
Status: r.ReplaceSlice(origTask.Status),
@@ -84,5 +85,15 @@ func (e *Executor) CompiledTask(call taskfile.Call) (*taskfile.Task, error) {
}
}
if len(origTask.Preconditions) > 0 {
new.Preconditions = make([]*taskfile.Precondition, len(origTask.Preconditions))
for i, precond := range origTask.Preconditions {
new.Preconditions[i] = &taskfile.Precondition{
Sh: r.Replace(precond.Sh),
Msg: r.Replace(precond.Msg),
}
}
}
return &new, r.Err()
}

View File

@@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2013 Mitchell Hashimoto
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.

View File

@@ -1,14 +0,0 @@
# go-homedir
This is a Go library for detecting the user's home directory without
the use of cgo, so the library can be used in cross-compilation environments.
Usage is incredibly simple, just call `homedir.Dir()` to get the home directory
for a user, and `homedir.Expand()` to expand the `~` in a path to the home
directory.
**Why not just use `os/user`?** The built-in `os/user` package requires
cgo on Darwin systems. This means that any Go code that uses that package
cannot cross compile. But 99% of the time the use for `os/user` is just to
retrieve the home directory, which we can do for the current user without
cgo. This library does that, enabling cross-compilation.

View File

@@ -1 +0,0 @@
module github.com/mitchellh/go-homedir

View File

@@ -1,157 +0,0 @@
package homedir
import (
"bytes"
"errors"
"os"
"os/exec"
"path/filepath"
"runtime"
"strconv"
"strings"
"sync"
)
// DisableCache will disable caching of the home directory. Caching is enabled
// by default.
var DisableCache bool
var homedirCache string
var cacheLock sync.RWMutex
// Dir returns the home directory for the executing user.
//
// This uses an OS-specific method for discovering the home directory.
// An error is returned if a home directory cannot be detected.
func Dir() (string, error) {
if !DisableCache {
cacheLock.RLock()
cached := homedirCache
cacheLock.RUnlock()
if cached != "" {
return cached, nil
}
}
cacheLock.Lock()
defer cacheLock.Unlock()
var result string
var err error
if runtime.GOOS == "windows" {
result, err = dirWindows()
} else {
// Unix-like system, so just assume Unix
result, err = dirUnix()
}
if err != nil {
return "", err
}
homedirCache = result
return result, nil
}
// Expand expands the path to include the home directory if the path
// is prefixed with `~`. If it isn't prefixed with `~`, the path is
// returned as-is.
func Expand(path string) (string, error) {
if len(path) == 0 {
return path, nil
}
if path[0] != '~' {
return path, nil
}
if len(path) > 1 && path[1] != '/' && path[1] != '\\' {
return "", errors.New("cannot expand user-specific home dir")
}
dir, err := Dir()
if err != nil {
return "", err
}
return filepath.Join(dir, path[1:]), nil
}
func dirUnix() (string, error) {
homeEnv := "HOME"
if runtime.GOOS == "plan9" {
// On plan9, env vars are lowercase.
homeEnv = "home"
}
// First prefer the HOME environmental variable
if home := os.Getenv(homeEnv); home != "" {
return home, nil
}
var stdout bytes.Buffer
// If that fails, try OS specific commands
if runtime.GOOS == "darwin" {
cmd := exec.Command("sh", "-c", `dscl -q . -read /Users/"$(whoami)" NFSHomeDirectory | sed 's/^[^ ]*: //'`)
cmd.Stdout = &stdout
if err := cmd.Run(); err == nil {
result := strings.TrimSpace(stdout.String())
if result != "" {
return result, nil
}
}
} else {
cmd := exec.Command("getent", "passwd", strconv.Itoa(os.Getuid()))
cmd.Stdout = &stdout
if err := cmd.Run(); err != nil {
// If the error is ErrNotFound, we ignore it. Otherwise, return it.
if err != exec.ErrNotFound {
return "", err
}
} else {
if passwd := strings.TrimSpace(stdout.String()); passwd != "" {
// username:password:uid:gid:gecos:home:shell
passwdParts := strings.SplitN(passwd, ":", 7)
if len(passwdParts) > 5 {
return passwdParts[5], nil
}
}
}
}
// If all else fails, try the shell
stdout.Reset()
cmd := exec.Command("sh", "-c", "cd && pwd")
cmd.Stdout = &stdout
if err := cmd.Run(); err != nil {
return "", err
}
result := strings.TrimSpace(stdout.String())
if result == "" {
return "", errors.New("blank output when reading home directory")
}
return result, nil
}
func dirWindows() (string, error) {
// First prefer the HOME environmental variable
if home := os.Getenv("HOME"); home != "" {
return home, nil
}
// Prefer standard environment variable USERPROFILE
if home := os.Getenv("USERPROFILE"); home != "" {
return home, nil
}
drive := os.Getenv("HOMEDRIVE")
path := os.Getenv("HOMEPATH")
home := drive + path
if drive == "" || path == "" {
return "", errors.New("HOMEDRIVE, HOMEPATH, or USERPROFILE are blank")
}
return home, nil
}

View File

@@ -113,6 +113,17 @@ func Errorf(t TestingT, err error, msg string, args ...interface{}) bool {
return Error(t, err, append([]interface{}{msg}, args...)...)
}
// Eventuallyf asserts that given condition will be met in waitFor time,
// periodically checking target function each tick.
//
// assert.Eventuallyf(t, func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted")
func Eventuallyf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
return Eventually(t, condition, waitFor, tick, append([]interface{}{msg}, args...)...)
}
// Exactlyf asserts that two objects are equal in value and type.
//
// assert.Exactlyf(t, int32(123, "error message %s", "formatted"), int64(123))
@@ -157,6 +168,31 @@ func FileExistsf(t TestingT, path string, msg string, args ...interface{}) bool
return FileExists(t, path, append([]interface{}{msg}, args...)...)
}
// Greaterf asserts that the first element is greater than the second
//
// assert.Greaterf(t, 2, 1, "error message %s", "formatted")
// assert.Greaterf(t, float64(2, "error message %s", "formatted"), float64(1))
// assert.Greaterf(t, "b", "a", "error message %s", "formatted")
func Greaterf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
return Greater(t, e1, e2, append([]interface{}{msg}, args...)...)
}
// GreaterOrEqualf asserts that the first element is greater than or equal to the second
//
// assert.GreaterOrEqualf(t, 2, 1, "error message %s", "formatted")
// assert.GreaterOrEqualf(t, 2, 2, "error message %s", "formatted")
// assert.GreaterOrEqualf(t, "b", "a", "error message %s", "formatted")
// assert.GreaterOrEqualf(t, "b", "b", "error message %s", "formatted")
func GreaterOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
return GreaterOrEqual(t, e1, e2, append([]interface{}{msg}, args...)...)
}
// HTTPBodyContainsf asserts that a specified handler returns a
// body that contains a string.
//
@@ -289,6 +325,14 @@ func JSONEqf(t TestingT, expected string, actual string, msg string, args ...int
return JSONEq(t, expected, actual, append([]interface{}{msg}, args...)...)
}
// YAMLEqf asserts that two YAML strings are equivalent.
func YAMLEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
return YAMLEq(t, expected, actual, append([]interface{}{msg}, args...)...)
}
// Lenf asserts that the specified object has specific length.
// Lenf also fails if the object has a type that len() not accept.
//
@@ -300,6 +344,31 @@ func Lenf(t TestingT, object interface{}, length int, msg string, args ...interf
return Len(t, object, length, append([]interface{}{msg}, args...)...)
}
// Lessf asserts that the first element is less than the second
//
// assert.Lessf(t, 1, 2, "error message %s", "formatted")
// assert.Lessf(t, float64(1, "error message %s", "formatted"), float64(2))
// assert.Lessf(t, "a", "b", "error message %s", "formatted")
func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
return Less(t, e1, e2, append([]interface{}{msg}, args...)...)
}
// LessOrEqualf asserts that the first element is less than or equal to the second
//
// assert.LessOrEqualf(t, 1, 2, "error message %s", "formatted")
// assert.LessOrEqualf(t, 2, 2, "error message %s", "formatted")
// assert.LessOrEqualf(t, "a", "b", "error message %s", "formatted")
// assert.LessOrEqualf(t, "b", "b", "error message %s", "formatted")
func LessOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
return LessOrEqual(t, e1, e2, append([]interface{}{msg}, args...)...)
}
// Nilf asserts that the specified object is nil.
//
// assert.Nilf(t, err, "error message %s", "formatted")
@@ -444,6 +513,19 @@ func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...in
return Regexp(t, rx, str, append([]interface{}{msg}, args...)...)
}
// Samef asserts that two pointers reference the same object.
//
// assert.Samef(t, ptr1, ptr2, "error message %s", "formatted")
//
// Both arguments must be pointer variables. Pointer variable sameness is
// determined based on the equality of both type and value.
func Samef(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
return Same(t, expected, actual, append([]interface{}{msg}, args...)...)
}
// Subsetf asserts that the specified list(array, slice...) contains all
// elements given in the specified subset(array, slice...).
//

View File

@@ -215,6 +215,28 @@ func (a *Assertions) Errorf(err error, msg string, args ...interface{}) bool {
return Errorf(a.t, err, msg, args...)
}
// Eventually asserts that given condition will be met in waitFor time,
// periodically checking target function each tick.
//
// a.Eventually(func() bool { return true; }, time.Second, 10*time.Millisecond)
func (a *Assertions) Eventually(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
return Eventually(a.t, condition, waitFor, tick, msgAndArgs...)
}
// Eventuallyf asserts that given condition will be met in waitFor time,
// periodically checking target function each tick.
//
// a.Eventuallyf(func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted")
func (a *Assertions) Eventuallyf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
return Eventuallyf(a.t, condition, waitFor, tick, msg, args...)
}
// Exactly asserts that two objects are equal in value and type.
//
// a.Exactly(int32(123), int64(123))
@@ -303,6 +325,56 @@ func (a *Assertions) FileExistsf(path string, msg string, args ...interface{}) b
return FileExistsf(a.t, path, msg, args...)
}
// Greater asserts that the first element is greater than the second
//
// a.Greater(2, 1)
// a.Greater(float64(2), float64(1))
// a.Greater("b", "a")
func (a *Assertions) Greater(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
return Greater(a.t, e1, e2, msgAndArgs...)
}
// GreaterOrEqual asserts that the first element is greater than or equal to the second
//
// a.GreaterOrEqual(2, 1)
// a.GreaterOrEqual(2, 2)
// a.GreaterOrEqual("b", "a")
// a.GreaterOrEqual("b", "b")
func (a *Assertions) GreaterOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
return GreaterOrEqual(a.t, e1, e2, msgAndArgs...)
}
// GreaterOrEqualf asserts that the first element is greater than or equal to the second
//
// a.GreaterOrEqualf(2, 1, "error message %s", "formatted")
// a.GreaterOrEqualf(2, 2, "error message %s", "formatted")
// a.GreaterOrEqualf("b", "a", "error message %s", "formatted")
// a.GreaterOrEqualf("b", "b", "error message %s", "formatted")
func (a *Assertions) GreaterOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
return GreaterOrEqualf(a.t, e1, e2, msg, args...)
}
// Greaterf asserts that the first element is greater than the second
//
// a.Greaterf(2, 1, "error message %s", "formatted")
// a.Greaterf(float64(2, "error message %s", "formatted"), float64(1))
// a.Greaterf("b", "a", "error message %s", "formatted")
func (a *Assertions) Greaterf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
return Greaterf(a.t, e1, e2, msg, args...)
}
// HTTPBodyContains asserts that a specified handler returns a
// body that contains a string.
//
@@ -567,6 +639,22 @@ func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ..
return JSONEqf(a.t, expected, actual, msg, args...)
}
// YAMLEq asserts that two YAML strings are equivalent.
func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
return YAMLEq(a.t, expected, actual, msgAndArgs...)
}
// YAMLEqf asserts that two YAML strings are equivalent.
func (a *Assertions) YAMLEqf(expected string, actual string, msg string, args ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
return YAMLEqf(a.t, expected, actual, msg, args...)
}
// Len asserts that the specified object has specific length.
// Len also fails if the object has a type that len() not accept.
//
@@ -589,6 +677,56 @@ func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...in
return Lenf(a.t, object, length, msg, args...)
}
// Less asserts that the first element is less than the second
//
// a.Less(1, 2)
// a.Less(float64(1), float64(2))
// a.Less("a", "b")
func (a *Assertions) Less(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
return Less(a.t, e1, e2, msgAndArgs...)
}
// LessOrEqual asserts that the first element is less than or equal to the second
//
// a.LessOrEqual(1, 2)
// a.LessOrEqual(2, 2)
// a.LessOrEqual("a", "b")
// a.LessOrEqual("b", "b")
func (a *Assertions) LessOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
return LessOrEqual(a.t, e1, e2, msgAndArgs...)
}
// LessOrEqualf asserts that the first element is less than or equal to the second
//
// a.LessOrEqualf(1, 2, "error message %s", "formatted")
// a.LessOrEqualf(2, 2, "error message %s", "formatted")
// a.LessOrEqualf("a", "b", "error message %s", "formatted")
// a.LessOrEqualf("b", "b", "error message %s", "formatted")
func (a *Assertions) LessOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
return LessOrEqualf(a.t, e1, e2, msg, args...)
}
// Lessf asserts that the first element is less than the second
//
// a.Lessf(1, 2, "error message %s", "formatted")
// a.Lessf(float64(1, "error message %s", "formatted"), float64(2))
// a.Lessf("a", "b", "error message %s", "formatted")
func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
return Lessf(a.t, e1, e2, msg, args...)
}
// Nil asserts that the specified object is nil.
//
// a.Nil(err)
@@ -877,6 +1015,32 @@ func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args .
return Regexpf(a.t, rx, str, msg, args...)
}
// Same asserts that two pointers reference the same object.
//
// a.Same(ptr1, ptr2)
//
// Both arguments must be pointer variables. Pointer variable sameness is
// determined based on the equality of both type and value.
func (a *Assertions) Same(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
return Same(a.t, expected, actual, msgAndArgs...)
}
// Samef asserts that two pointers reference the same object.
//
// a.Samef(ptr1, ptr2, "error message %s", "formatted")
//
// Both arguments must be pointer variables. Pointer variable sameness is
// determined based on the equality of both type and value.
func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
return Samef(a.t, expected, actual, msg, args...)
}
// Subset asserts that the specified list(array, slice...) contains all
// elements given in the specified subset(array, slice...).
//

View File

@@ -0,0 +1,309 @@
package assert
import (
"fmt"
"reflect"
)
func compare(obj1, obj2 interface{}, kind reflect.Kind) (int, bool) {
switch kind {
case reflect.Int:
{
intobj1 := obj1.(int)
intobj2 := obj2.(int)
if intobj1 > intobj2 {
return -1, true
}
if intobj1 == intobj2 {
return 0, true
}
if intobj1 < intobj2 {
return 1, true
}
}
case reflect.Int8:
{
int8obj1 := obj1.(int8)
int8obj2 := obj2.(int8)
if int8obj1 > int8obj2 {
return -1, true
}
if int8obj1 == int8obj2 {
return 0, true
}
if int8obj1 < int8obj2 {
return 1, true
}
}
case reflect.Int16:
{
int16obj1 := obj1.(int16)
int16obj2 := obj2.(int16)
if int16obj1 > int16obj2 {
return -1, true
}
if int16obj1 == int16obj2 {
return 0, true
}
if int16obj1 < int16obj2 {
return 1, true
}
}
case reflect.Int32:
{
int32obj1 := obj1.(int32)
int32obj2 := obj2.(int32)
if int32obj1 > int32obj2 {
return -1, true
}
if int32obj1 == int32obj2 {
return 0, true
}
if int32obj1 < int32obj2 {
return 1, true
}
}
case reflect.Int64:
{
int64obj1 := obj1.(int64)
int64obj2 := obj2.(int64)
if int64obj1 > int64obj2 {
return -1, true
}
if int64obj1 == int64obj2 {
return 0, true
}
if int64obj1 < int64obj2 {
return 1, true
}
}
case reflect.Uint:
{
uintobj1 := obj1.(uint)
uintobj2 := obj2.(uint)
if uintobj1 > uintobj2 {
return -1, true
}
if uintobj1 == uintobj2 {
return 0, true
}
if uintobj1 < uintobj2 {
return 1, true
}
}
case reflect.Uint8:
{
uint8obj1 := obj1.(uint8)
uint8obj2 := obj2.(uint8)
if uint8obj1 > uint8obj2 {
return -1, true
}
if uint8obj1 == uint8obj2 {
return 0, true
}
if uint8obj1 < uint8obj2 {
return 1, true
}
}
case reflect.Uint16:
{
uint16obj1 := obj1.(uint16)
uint16obj2 := obj2.(uint16)
if uint16obj1 > uint16obj2 {
return -1, true
}
if uint16obj1 == uint16obj2 {
return 0, true
}
if uint16obj1 < uint16obj2 {
return 1, true
}
}
case reflect.Uint32:
{
uint32obj1 := obj1.(uint32)
uint32obj2 := obj2.(uint32)
if uint32obj1 > uint32obj2 {
return -1, true
}
if uint32obj1 == uint32obj2 {
return 0, true
}
if uint32obj1 < uint32obj2 {
return 1, true
}
}
case reflect.Uint64:
{
uint64obj1 := obj1.(uint64)
uint64obj2 := obj2.(uint64)
if uint64obj1 > uint64obj2 {
return -1, true
}
if uint64obj1 == uint64obj2 {
return 0, true
}
if uint64obj1 < uint64obj2 {
return 1, true
}
}
case reflect.Float32:
{
float32obj1 := obj1.(float32)
float32obj2 := obj2.(float32)
if float32obj1 > float32obj2 {
return -1, true
}
if float32obj1 == float32obj2 {
return 0, true
}
if float32obj1 < float32obj2 {
return 1, true
}
}
case reflect.Float64:
{
float64obj1 := obj1.(float64)
float64obj2 := obj2.(float64)
if float64obj1 > float64obj2 {
return -1, true
}
if float64obj1 == float64obj2 {
return 0, true
}
if float64obj1 < float64obj2 {
return 1, true
}
}
case reflect.String:
{
stringobj1 := obj1.(string)
stringobj2 := obj2.(string)
if stringobj1 > stringobj2 {
return -1, true
}
if stringobj1 == stringobj2 {
return 0, true
}
if stringobj1 < stringobj2 {
return 1, true
}
}
}
return 0, false
}
// Greater asserts that the first element is greater than the second
//
// assert.Greater(t, 2, 1)
// assert.Greater(t, float64(2), float64(1))
// assert.Greater(t, "b", "a")
func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
e1Kind := reflect.ValueOf(e1).Kind()
e2Kind := reflect.ValueOf(e2).Kind()
if e1Kind != e2Kind {
return Fail(t, "Elements should be the same type", msgAndArgs...)
}
res, isComparable := compare(e1, e2, e1Kind)
if !isComparable {
return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...)
}
if res != -1 {
return Fail(t, fmt.Sprintf("\"%v\" is not greater than \"%v\"", e1, e2), msgAndArgs...)
}
return true
}
// GreaterOrEqual asserts that the first element is greater than or equal to the second
//
// assert.GreaterOrEqual(t, 2, 1)
// assert.GreaterOrEqual(t, 2, 2)
// assert.GreaterOrEqual(t, "b", "a")
// assert.GreaterOrEqual(t, "b", "b")
func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
e1Kind := reflect.ValueOf(e1).Kind()
e2Kind := reflect.ValueOf(e2).Kind()
if e1Kind != e2Kind {
return Fail(t, "Elements should be the same type", msgAndArgs...)
}
res, isComparable := compare(e1, e2, e1Kind)
if !isComparable {
return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...)
}
if res != -1 && res != 0 {
return Fail(t, fmt.Sprintf("\"%v\" is not greater than or equal to \"%v\"", e1, e2), msgAndArgs...)
}
return true
}
// Less asserts that the first element is less than the second
//
// assert.Less(t, 1, 2)
// assert.Less(t, float64(1), float64(2))
// assert.Less(t, "a", "b")
func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
e1Kind := reflect.ValueOf(e1).Kind()
e2Kind := reflect.ValueOf(e2).Kind()
if e1Kind != e2Kind {
return Fail(t, "Elements should be the same type", msgAndArgs...)
}
res, isComparable := compare(e1, e2, e1Kind)
if !isComparable {
return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...)
}
if res != 1 {
return Fail(t, fmt.Sprintf("\"%v\" is not less than \"%v\"", e1, e2), msgAndArgs...)
}
return true
}
// LessOrEqual asserts that the first element is less than or equal to the second
//
// assert.LessOrEqual(t, 1, 2)
// assert.LessOrEqual(t, 2, 2)
// assert.LessOrEqual(t, "a", "b")
// assert.LessOrEqual(t, "b", "b")
func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
e1Kind := reflect.ValueOf(e1).Kind()
e2Kind := reflect.ValueOf(e2).Kind()
if e1Kind != e2Kind {
return Fail(t, "Elements should be the same type", msgAndArgs...)
}
res, isComparable := compare(e1, e2, e1Kind)
if !isComparable {
return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...)
}
if res != 1 && res != 0 {
return Fail(t, fmt.Sprintf("\"%v\" is not less than or equal to \"%v\"", e1, e2), msgAndArgs...)
}
return true
}

View File

@@ -18,6 +18,7 @@ import (
"github.com/davecgh/go-spew/spew"
"github.com/pmezard/go-difflib/difflib"
yaml "gopkg.in/yaml.v2"
)
//go:generate go run ../_codegen/main.go -output-package=assert -template=assertion_format.go.tmpl
@@ -350,6 +351,37 @@ func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{})
}
// Same asserts that two pointers reference the same object.
//
// assert.Same(t, ptr1, ptr2)
//
// Both arguments must be pointer variables. Pointer variable sameness is
// determined based on the equality of both type and value.
func Same(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
expectedPtr, actualPtr := reflect.ValueOf(expected), reflect.ValueOf(actual)
if expectedPtr.Kind() != reflect.Ptr || actualPtr.Kind() != reflect.Ptr {
return Fail(t, "Invalid operation: both arguments must be pointers", msgAndArgs...)
}
expectedType, actualType := reflect.TypeOf(expected), reflect.TypeOf(actual)
if expectedType != actualType {
return Fail(t, fmt.Sprintf("Pointer expected to be of type %v, but was %v",
expectedType, actualType), msgAndArgs...)
}
if expected != actual {
return Fail(t, fmt.Sprintf("Not same: \n"+
"expected: %p %#v\n"+
"actual : %p %#v", expected, expected, actual, actual), msgAndArgs...)
}
return true
}
// formatUnequalValues takes two values of arbitrary types and returns string
// representations appropriate to be presented to the user.
//
@@ -479,14 +511,14 @@ func isEmpty(object interface{}) bool {
// collection types are empty when they have no element
case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:
return objValue.Len() == 0
// pointers are empty if nil or if the value they point to is empty
// pointers are empty if nil or if the value they point to is empty
case reflect.Ptr:
if objValue.IsNil() {
return true
}
deref := objValue.Elem().Interface()
return isEmpty(deref)
// for all other types, compare against the zero value
// for all other types, compare against the zero value
default:
zero := reflect.Zero(objValue.Type())
return reflect.DeepEqual(object, zero.Interface())
@@ -629,7 +661,7 @@ func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{
func includeElement(list interface{}, element interface{}) (ok, found bool) {
listValue := reflect.ValueOf(list)
elementValue := reflect.ValueOf(element)
listKind := reflect.TypeOf(list).Kind()
defer func() {
if e := recover(); e != nil {
ok = false
@@ -637,11 +669,12 @@ func includeElement(list interface{}, element interface{}) (ok, found bool) {
}
}()
if reflect.TypeOf(list).Kind() == reflect.String {
if listKind == reflect.String {
elementValue := reflect.ValueOf(element)
return true, strings.Contains(listValue.String(), elementValue.String())
}
if reflect.TypeOf(list).Kind() == reflect.Map {
if listKind == reflect.Map {
mapKeys := listValue.MapKeys()
for i := 0; i < len(mapKeys); i++ {
if ObjectsAreEqual(mapKeys[i].Interface(), element) {
@@ -1337,6 +1370,24 @@ func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{
return Equal(t, expectedJSONAsInterface, actualJSONAsInterface, msgAndArgs...)
}
// YAMLEq asserts that two YAML strings are equivalent.
func YAMLEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
var expectedYAMLAsInterface, actualYAMLAsInterface interface{}
if err := yaml.Unmarshal([]byte(expected), &expectedYAMLAsInterface); err != nil {
return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid yaml.\nYAML parsing error: '%s'", expected, err.Error()), msgAndArgs...)
}
if err := yaml.Unmarshal([]byte(actual), &actualYAMLAsInterface); err != nil {
return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid yaml.\nYAML error: '%s'", actual, err.Error()), msgAndArgs...)
}
return Equal(t, expectedYAMLAsInterface, actualYAMLAsInterface, msgAndArgs...)
}
func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) {
t := reflect.TypeOf(v)
k := t.Kind()
@@ -1371,8 +1422,8 @@ func diff(expected interface{}, actual interface{}) string {
e = spewConfig.Sdump(expected)
a = spewConfig.Sdump(actual)
} else {
e = expected.(string)
a = actual.(string)
e = reflect.ValueOf(expected).String()
a = reflect.ValueOf(actual).String()
}
diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{
@@ -1414,3 +1465,34 @@ var spewConfig = spew.ConfigState{
type tHelper interface {
Helper()
}
// Eventually asserts that given condition will be met in waitFor time,
// periodically checking target function each tick.
//
// assert.Eventually(t, func() bool { return true; }, time.Second, 10*time.Millisecond)
func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
timer := time.NewTimer(waitFor)
ticker := time.NewTicker(tick)
checkPassed := make(chan bool)
defer timer.Stop()
defer ticker.Stop()
defer close(checkPassed)
for {
select {
case <-timer.C:
return Fail(t, "Condition never satisfied", msgAndArgs...)
case result := <-checkPassed:
if result {
return true
}
case <-ticker.C:
go func() {
checkPassed <- condition()
}()
}
}
}

View File

@@ -10,6 +10,7 @@ package scrypt // import "golang.org/x/crypto/scrypt"
import (
"crypto/sha256"
"errors"
"math/bits"
"golang.org/x/crypto/pbkdf2"
)
@@ -29,7 +30,7 @@ func blockXOR(dst, src []uint32, n int) {
}
// salsaXOR applies Salsa20/8 to the XOR of 16 numbers from tmp and in,
// and puts the result into both both tmp and out.
// and puts the result into both tmp and out.
func salsaXOR(tmp *[16]uint32, in, out []uint32) {
w0 := tmp[0] ^ in[0]
w1 := tmp[1] ^ in[1]
@@ -52,77 +53,45 @@ func salsaXOR(tmp *[16]uint32, in, out []uint32) {
x9, x10, x11, x12, x13, x14, x15 := w9, w10, w11, w12, w13, w14, w15
for i := 0; i < 8; i += 2 {
u := x0 + x12
x4 ^= u<<7 | u>>(32-7)
u = x4 + x0
x8 ^= u<<9 | u>>(32-9)
u = x8 + x4
x12 ^= u<<13 | u>>(32-13)
u = x12 + x8
x0 ^= u<<18 | u>>(32-18)
x4 ^= bits.RotateLeft32(x0+x12, 7)
x8 ^= bits.RotateLeft32(x4+x0, 9)
x12 ^= bits.RotateLeft32(x8+x4, 13)
x0 ^= bits.RotateLeft32(x12+x8, 18)
u = x5 + x1
x9 ^= u<<7 | u>>(32-7)
u = x9 + x5
x13 ^= u<<9 | u>>(32-9)
u = x13 + x9
x1 ^= u<<13 | u>>(32-13)
u = x1 + x13
x5 ^= u<<18 | u>>(32-18)
x9 ^= bits.RotateLeft32(x5+x1, 7)
x13 ^= bits.RotateLeft32(x9+x5, 9)
x1 ^= bits.RotateLeft32(x13+x9, 13)
x5 ^= bits.RotateLeft32(x1+x13, 18)
u = x10 + x6
x14 ^= u<<7 | u>>(32-7)
u = x14 + x10
x2 ^= u<<9 | u>>(32-9)
u = x2 + x14
x6 ^= u<<13 | u>>(32-13)
u = x6 + x2
x10 ^= u<<18 | u>>(32-18)
x14 ^= bits.RotateLeft32(x10+x6, 7)
x2 ^= bits.RotateLeft32(x14+x10, 9)
x6 ^= bits.RotateLeft32(x2+x14, 13)
x10 ^= bits.RotateLeft32(x6+x2, 18)
u = x15 + x11
x3 ^= u<<7 | u>>(32-7)
u = x3 + x15
x7 ^= u<<9 | u>>(32-9)
u = x7 + x3
x11 ^= u<<13 | u>>(32-13)
u = x11 + x7
x15 ^= u<<18 | u>>(32-18)
x3 ^= bits.RotateLeft32(x15+x11, 7)
x7 ^= bits.RotateLeft32(x3+x15, 9)
x11 ^= bits.RotateLeft32(x7+x3, 13)
x15 ^= bits.RotateLeft32(x11+x7, 18)
u = x0 + x3
x1 ^= u<<7 | u>>(32-7)
u = x1 + x0
x2 ^= u<<9 | u>>(32-9)
u = x2 + x1
x3 ^= u<<13 | u>>(32-13)
u = x3 + x2
x0 ^= u<<18 | u>>(32-18)
x1 ^= bits.RotateLeft32(x0+x3, 7)
x2 ^= bits.RotateLeft32(x1+x0, 9)
x3 ^= bits.RotateLeft32(x2+x1, 13)
x0 ^= bits.RotateLeft32(x3+x2, 18)
u = x5 + x4
x6 ^= u<<7 | u>>(32-7)
u = x6 + x5
x7 ^= u<<9 | u>>(32-9)
u = x7 + x6
x4 ^= u<<13 | u>>(32-13)
u = x4 + x7
x5 ^= u<<18 | u>>(32-18)
x6 ^= bits.RotateLeft32(x5+x4, 7)
x7 ^= bits.RotateLeft32(x6+x5, 9)
x4 ^= bits.RotateLeft32(x7+x6, 13)
x5 ^= bits.RotateLeft32(x4+x7, 18)
u = x10 + x9
x11 ^= u<<7 | u>>(32-7)
u = x11 + x10
x8 ^= u<<9 | u>>(32-9)
u = x8 + x11
x9 ^= u<<13 | u>>(32-13)
u = x9 + x8
x10 ^= u<<18 | u>>(32-18)
x11 ^= bits.RotateLeft32(x10+x9, 7)
x8 ^= bits.RotateLeft32(x11+x10, 9)
x9 ^= bits.RotateLeft32(x8+x11, 13)
x10 ^= bits.RotateLeft32(x9+x8, 18)
u = x15 + x14
x12 ^= u<<7 | u>>(32-7)
u = x12 + x15
x13 ^= u<<9 | u>>(32-9)
u = x13 + x12
x14 ^= u<<13 | u>>(32-13)
u = x14 + x13
x15 ^= u<<18 | u>>(32-18)
x12 ^= bits.RotateLeft32(x15+x14, 7)
x13 ^= bits.RotateLeft32(x12+x15, 9)
x14 ^= bits.RotateLeft32(x13+x12, 13)
x15 ^= bits.RotateLeft32(x14+x13, 18)
}
x0 += w0
x1 += w1

View File

@@ -1,951 +0,0 @@
// 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 terminal
import (
"bytes"
"io"
"sync"
"unicode/utf8"
)
// EscapeCodes contains escape sequences that can be written to the terminal in
// order to achieve different styles of text.
type EscapeCodes struct {
// Foreground colors
Black, Red, Green, Yellow, Blue, Magenta, Cyan, White []byte
// Reset all attributes
Reset []byte
}
var vt100EscapeCodes = EscapeCodes{
Black: []byte{keyEscape, '[', '3', '0', 'm'},
Red: []byte{keyEscape, '[', '3', '1', 'm'},
Green: []byte{keyEscape, '[', '3', '2', 'm'},
Yellow: []byte{keyEscape, '[', '3', '3', 'm'},
Blue: []byte{keyEscape, '[', '3', '4', 'm'},
Magenta: []byte{keyEscape, '[', '3', '5', 'm'},
Cyan: []byte{keyEscape, '[', '3', '6', 'm'},
White: []byte{keyEscape, '[', '3', '7', 'm'},
Reset: []byte{keyEscape, '[', '0', 'm'},
}
// Terminal contains the state for running a VT100 terminal that is capable of
// reading lines of input.
type Terminal struct {
// AutoCompleteCallback, if non-null, is called for each keypress with
// the full input line and the current position of the cursor (in
// bytes, as an index into |line|). If it returns ok=false, the key
// press is processed normally. Otherwise it returns a replacement line
// and the new cursor position.
AutoCompleteCallback func(line string, pos int, key rune) (newLine string, newPos int, ok bool)
// Escape contains a pointer to the escape codes for this terminal.
// It's always a valid pointer, although the escape codes themselves
// may be empty if the terminal doesn't support them.
Escape *EscapeCodes
// lock protects the terminal and the state in this object from
// concurrent processing of a key press and a Write() call.
lock sync.Mutex
c io.ReadWriter
prompt []rune
// line is the current line being entered.
line []rune
// pos is the logical position of the cursor in line
pos int
// echo is true if local echo is enabled
echo bool
// pasteActive is true iff there is a bracketed paste operation in
// progress.
pasteActive bool
// cursorX contains the current X value of the cursor where the left
// edge is 0. cursorY contains the row number where the first row of
// the current line is 0.
cursorX, cursorY int
// maxLine is the greatest value of cursorY so far.
maxLine int
termWidth, termHeight int
// outBuf contains the terminal data to be sent.
outBuf []byte
// remainder contains the remainder of any partial key sequences after
// a read. It aliases into inBuf.
remainder []byte
inBuf [256]byte
// history contains previously entered commands so that they can be
// accessed with the up and down keys.
history stRingBuffer
// historyIndex stores the currently accessed history entry, where zero
// means the immediately previous entry.
historyIndex int
// When navigating up and down the history it's possible to return to
// the incomplete, initial line. That value is stored in
// historyPending.
historyPending string
}
// NewTerminal runs a VT100 terminal on the given ReadWriter. If the ReadWriter is
// a local terminal, that terminal must first have been put into raw mode.
// prompt is a string that is written at the start of each input line (i.e.
// "> ").
func NewTerminal(c io.ReadWriter, prompt string) *Terminal {
return &Terminal{
Escape: &vt100EscapeCodes,
c: c,
prompt: []rune(prompt),
termWidth: 80,
termHeight: 24,
echo: true,
historyIndex: -1,
}
}
const (
keyCtrlD = 4
keyCtrlU = 21
keyEnter = '\r'
keyEscape = 27
keyBackspace = 127
keyUnknown = 0xd800 /* UTF-16 surrogate area */ + iota
keyUp
keyDown
keyLeft
keyRight
keyAltLeft
keyAltRight
keyHome
keyEnd
keyDeleteWord
keyDeleteLine
keyClearScreen
keyPasteStart
keyPasteEnd
)
var (
crlf = []byte{'\r', '\n'}
pasteStart = []byte{keyEscape, '[', '2', '0', '0', '~'}
pasteEnd = []byte{keyEscape, '[', '2', '0', '1', '~'}
)
// bytesToKey tries to parse a key sequence from b. If successful, it returns
// the key and the remainder of the input. Otherwise it returns utf8.RuneError.
func bytesToKey(b []byte, pasteActive bool) (rune, []byte) {
if len(b) == 0 {
return utf8.RuneError, nil
}
if !pasteActive {
switch b[0] {
case 1: // ^A
return keyHome, b[1:]
case 5: // ^E
return keyEnd, b[1:]
case 8: // ^H
return keyBackspace, b[1:]
case 11: // ^K
return keyDeleteLine, b[1:]
case 12: // ^L
return keyClearScreen, b[1:]
case 23: // ^W
return keyDeleteWord, b[1:]
}
}
if b[0] != keyEscape {
if !utf8.FullRune(b) {
return utf8.RuneError, b
}
r, l := utf8.DecodeRune(b)
return r, b[l:]
}
if !pasteActive && len(b) >= 3 && b[0] == keyEscape && b[1] == '[' {
switch b[2] {
case 'A':
return keyUp, b[3:]
case 'B':
return keyDown, b[3:]
case 'C':
return keyRight, b[3:]
case 'D':
return keyLeft, b[3:]
case 'H':
return keyHome, b[3:]
case 'F':
return keyEnd, b[3:]
}
}
if !pasteActive && len(b) >= 6 && b[0] == keyEscape && b[1] == '[' && b[2] == '1' && b[3] == ';' && b[4] == '3' {
switch b[5] {
case 'C':
return keyAltRight, b[6:]
case 'D':
return keyAltLeft, b[6:]
}
}
if !pasteActive && len(b) >= 6 && bytes.Equal(b[:6], pasteStart) {
return keyPasteStart, b[6:]
}
if pasteActive && len(b) >= 6 && bytes.Equal(b[:6], pasteEnd) {
return keyPasteEnd, b[6:]
}
// If we get here then we have a key that we don't recognise, or a
// partial sequence. It's not clear how one should find the end of a
// sequence without knowing them all, but it seems that [a-zA-Z~] only
// appears at the end of a sequence.
for i, c := range b[0:] {
if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '~' {
return keyUnknown, b[i+1:]
}
}
return utf8.RuneError, b
}
// queue appends data to the end of t.outBuf
func (t *Terminal) queue(data []rune) {
t.outBuf = append(t.outBuf, []byte(string(data))...)
}
var eraseUnderCursor = []rune{' ', keyEscape, '[', 'D'}
var space = []rune{' '}
func isPrintable(key rune) bool {
isInSurrogateArea := key >= 0xd800 && key <= 0xdbff
return key >= 32 && !isInSurrogateArea
}
// moveCursorToPos appends data to t.outBuf which will move the cursor to the
// given, logical position in the text.
func (t *Terminal) moveCursorToPos(pos int) {
if !t.echo {
return
}
x := visualLength(t.prompt) + pos
y := x / t.termWidth
x = x % t.termWidth
up := 0
if y < t.cursorY {
up = t.cursorY - y
}
down := 0
if y > t.cursorY {
down = y - t.cursorY
}
left := 0
if x < t.cursorX {
left = t.cursorX - x
}
right := 0
if x > t.cursorX {
right = x - t.cursorX
}
t.cursorX = x
t.cursorY = y
t.move(up, down, left, right)
}
func (t *Terminal) move(up, down, left, right int) {
movement := make([]rune, 3*(up+down+left+right))
m := movement
for i := 0; i < up; i++ {
m[0] = keyEscape
m[1] = '['
m[2] = 'A'
m = m[3:]
}
for i := 0; i < down; i++ {
m[0] = keyEscape
m[1] = '['
m[2] = 'B'
m = m[3:]
}
for i := 0; i < left; i++ {
m[0] = keyEscape
m[1] = '['
m[2] = 'D'
m = m[3:]
}
for i := 0; i < right; i++ {
m[0] = keyEscape
m[1] = '['
m[2] = 'C'
m = m[3:]
}
t.queue(movement)
}
func (t *Terminal) clearLineToRight() {
op := []rune{keyEscape, '[', 'K'}
t.queue(op)
}
const maxLineLength = 4096
func (t *Terminal) setLine(newLine []rune, newPos int) {
if t.echo {
t.moveCursorToPos(0)
t.writeLine(newLine)
for i := len(newLine); i < len(t.line); i++ {
t.writeLine(space)
}
t.moveCursorToPos(newPos)
}
t.line = newLine
t.pos = newPos
}
func (t *Terminal) advanceCursor(places int) {
t.cursorX += places
t.cursorY += t.cursorX / t.termWidth
if t.cursorY > t.maxLine {
t.maxLine = t.cursorY
}
t.cursorX = t.cursorX % t.termWidth
if places > 0 && t.cursorX == 0 {
// Normally terminals will advance the current position
// when writing a character. But that doesn't happen
// for the last character in a line. However, when
// writing a character (except a new line) that causes
// a line wrap, the position will be advanced two
// places.
//
// So, if we are stopping at the end of a line, we
// need to write a newline so that our cursor can be
// advanced to the next line.
t.outBuf = append(t.outBuf, '\r', '\n')
}
}
func (t *Terminal) eraseNPreviousChars(n int) {
if n == 0 {
return
}
if t.pos < n {
n = t.pos
}
t.pos -= n
t.moveCursorToPos(t.pos)
copy(t.line[t.pos:], t.line[n+t.pos:])
t.line = t.line[:len(t.line)-n]
if t.echo {
t.writeLine(t.line[t.pos:])
for i := 0; i < n; i++ {
t.queue(space)
}
t.advanceCursor(n)
t.moveCursorToPos(t.pos)
}
}
// countToLeftWord returns then number of characters from the cursor to the
// start of the previous word.
func (t *Terminal) countToLeftWord() int {
if t.pos == 0 {
return 0
}
pos := t.pos - 1
for pos > 0 {
if t.line[pos] != ' ' {
break
}
pos--
}
for pos > 0 {
if t.line[pos] == ' ' {
pos++
break
}
pos--
}
return t.pos - pos
}
// countToRightWord returns then number of characters from the cursor to the
// start of the next word.
func (t *Terminal) countToRightWord() int {
pos := t.pos
for pos < len(t.line) {
if t.line[pos] == ' ' {
break
}
pos++
}
for pos < len(t.line) {
if t.line[pos] != ' ' {
break
}
pos++
}
return pos - t.pos
}
// visualLength returns the number of visible glyphs in s.
func visualLength(runes []rune) int {
inEscapeSeq := false
length := 0
for _, r := range runes {
switch {
case inEscapeSeq:
if (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') {
inEscapeSeq = false
}
case r == '\x1b':
inEscapeSeq = true
default:
length++
}
}
return length
}
// handleKey processes the given key and, optionally, returns a line of text
// that the user has entered.
func (t *Terminal) handleKey(key rune) (line string, ok bool) {
if t.pasteActive && key != keyEnter {
t.addKeyToLine(key)
return
}
switch key {
case keyBackspace:
if t.pos == 0 {
return
}
t.eraseNPreviousChars(1)
case keyAltLeft:
// move left by a word.
t.pos -= t.countToLeftWord()
t.moveCursorToPos(t.pos)
case keyAltRight:
// move right by a word.
t.pos += t.countToRightWord()
t.moveCursorToPos(t.pos)
case keyLeft:
if t.pos == 0 {
return
}
t.pos--
t.moveCursorToPos(t.pos)
case keyRight:
if t.pos == len(t.line) {
return
}
t.pos++
t.moveCursorToPos(t.pos)
case keyHome:
if t.pos == 0 {
return
}
t.pos = 0
t.moveCursorToPos(t.pos)
case keyEnd:
if t.pos == len(t.line) {
return
}
t.pos = len(t.line)
t.moveCursorToPos(t.pos)
case keyUp:
entry, ok := t.history.NthPreviousEntry(t.historyIndex + 1)
if !ok {
return "", false
}
if t.historyIndex == -1 {
t.historyPending = string(t.line)
}
t.historyIndex++
runes := []rune(entry)
t.setLine(runes, len(runes))
case keyDown:
switch t.historyIndex {
case -1:
return
case 0:
runes := []rune(t.historyPending)
t.setLine(runes, len(runes))
t.historyIndex--
default:
entry, ok := t.history.NthPreviousEntry(t.historyIndex - 1)
if ok {
t.historyIndex--
runes := []rune(entry)
t.setLine(runes, len(runes))
}
}
case keyEnter:
t.moveCursorToPos(len(t.line))
t.queue([]rune("\r\n"))
line = string(t.line)
ok = true
t.line = t.line[:0]
t.pos = 0
t.cursorX = 0
t.cursorY = 0
t.maxLine = 0
case keyDeleteWord:
// Delete zero or more spaces and then one or more characters.
t.eraseNPreviousChars(t.countToLeftWord())
case keyDeleteLine:
// Delete everything from the current cursor position to the
// end of line.
for i := t.pos; i < len(t.line); i++ {
t.queue(space)
t.advanceCursor(1)
}
t.line = t.line[:t.pos]
t.moveCursorToPos(t.pos)
case keyCtrlD:
// Erase the character under the current position.
// The EOF case when the line is empty is handled in
// readLine().
if t.pos < len(t.line) {
t.pos++
t.eraseNPreviousChars(1)
}
case keyCtrlU:
t.eraseNPreviousChars(t.pos)
case keyClearScreen:
// Erases the screen and moves the cursor to the home position.
t.queue([]rune("\x1b[2J\x1b[H"))
t.queue(t.prompt)
t.cursorX, t.cursorY = 0, 0
t.advanceCursor(visualLength(t.prompt))
t.setLine(t.line, t.pos)
default:
if t.AutoCompleteCallback != nil {
prefix := string(t.line[:t.pos])
suffix := string(t.line[t.pos:])
t.lock.Unlock()
newLine, newPos, completeOk := t.AutoCompleteCallback(prefix+suffix, len(prefix), key)
t.lock.Lock()
if completeOk {
t.setLine([]rune(newLine), utf8.RuneCount([]byte(newLine)[:newPos]))
return
}
}
if !isPrintable(key) {
return
}
if len(t.line) == maxLineLength {
return
}
t.addKeyToLine(key)
}
return
}
// addKeyToLine inserts the given key at the current position in the current
// line.
func (t *Terminal) addKeyToLine(key rune) {
if len(t.line) == cap(t.line) {
newLine := make([]rune, len(t.line), 2*(1+len(t.line)))
copy(newLine, t.line)
t.line = newLine
}
t.line = t.line[:len(t.line)+1]
copy(t.line[t.pos+1:], t.line[t.pos:])
t.line[t.pos] = key
if t.echo {
t.writeLine(t.line[t.pos:])
}
t.pos++
t.moveCursorToPos(t.pos)
}
func (t *Terminal) writeLine(line []rune) {
for len(line) != 0 {
remainingOnLine := t.termWidth - t.cursorX
todo := len(line)
if todo > remainingOnLine {
todo = remainingOnLine
}
t.queue(line[:todo])
t.advanceCursor(visualLength(line[:todo]))
line = line[todo:]
}
}
// writeWithCRLF writes buf to w but replaces all occurrences of \n with \r\n.
func writeWithCRLF(w io.Writer, buf []byte) (n int, err error) {
for len(buf) > 0 {
i := bytes.IndexByte(buf, '\n')
todo := len(buf)
if i >= 0 {
todo = i
}
var nn int
nn, err = w.Write(buf[:todo])
n += nn
if err != nil {
return n, err
}
buf = buf[todo:]
if i >= 0 {
if _, err = w.Write(crlf); err != nil {
return n, err
}
n++
buf = buf[1:]
}
}
return n, nil
}
func (t *Terminal) Write(buf []byte) (n int, err error) {
t.lock.Lock()
defer t.lock.Unlock()
if t.cursorX == 0 && t.cursorY == 0 {
// This is the easy case: there's nothing on the screen that we
// have to move out of the way.
return writeWithCRLF(t.c, buf)
}
// We have a prompt and possibly user input on the screen. We
// have to clear it first.
t.move(0 /* up */, 0 /* down */, t.cursorX /* left */, 0 /* right */)
t.cursorX = 0
t.clearLineToRight()
for t.cursorY > 0 {
t.move(1 /* up */, 0, 0, 0)
t.cursorY--
t.clearLineToRight()
}
if _, err = t.c.Write(t.outBuf); err != nil {
return
}
t.outBuf = t.outBuf[:0]
if n, err = writeWithCRLF(t.c, buf); err != nil {
return
}
t.writeLine(t.prompt)
if t.echo {
t.writeLine(t.line)
}
t.moveCursorToPos(t.pos)
if _, err = t.c.Write(t.outBuf); err != nil {
return
}
t.outBuf = t.outBuf[:0]
return
}
// ReadPassword temporarily changes the prompt and reads a password, without
// echo, from the terminal.
func (t *Terminal) ReadPassword(prompt string) (line string, err error) {
t.lock.Lock()
defer t.lock.Unlock()
oldPrompt := t.prompt
t.prompt = []rune(prompt)
t.echo = false
line, err = t.readLine()
t.prompt = oldPrompt
t.echo = true
return
}
// ReadLine returns a line of input from the terminal.
func (t *Terminal) ReadLine() (line string, err error) {
t.lock.Lock()
defer t.lock.Unlock()
return t.readLine()
}
func (t *Terminal) readLine() (line string, err error) {
// t.lock must be held at this point
if t.cursorX == 0 && t.cursorY == 0 {
t.writeLine(t.prompt)
t.c.Write(t.outBuf)
t.outBuf = t.outBuf[:0]
}
lineIsPasted := t.pasteActive
for {
rest := t.remainder
lineOk := false
for !lineOk {
var key rune
key, rest = bytesToKey(rest, t.pasteActive)
if key == utf8.RuneError {
break
}
if !t.pasteActive {
if key == keyCtrlD {
if len(t.line) == 0 {
return "", io.EOF
}
}
if key == keyPasteStart {
t.pasteActive = true
if len(t.line) == 0 {
lineIsPasted = true
}
continue
}
} else if key == keyPasteEnd {
t.pasteActive = false
continue
}
if !t.pasteActive {
lineIsPasted = false
}
line, lineOk = t.handleKey(key)
}
if len(rest) > 0 {
n := copy(t.inBuf[:], rest)
t.remainder = t.inBuf[:n]
} else {
t.remainder = nil
}
t.c.Write(t.outBuf)
t.outBuf = t.outBuf[:0]
if lineOk {
if t.echo {
t.historyIndex = -1
t.history.Add(line)
}
if lineIsPasted {
err = ErrPasteIndicator
}
return
}
// t.remainder is a slice at the beginning of t.inBuf
// containing a partial key sequence
readBuf := t.inBuf[len(t.remainder):]
var n int
t.lock.Unlock()
n, err = t.c.Read(readBuf)
t.lock.Lock()
if err != nil {
return
}
t.remainder = t.inBuf[:n+len(t.remainder)]
}
}
// SetPrompt sets the prompt to be used when reading subsequent lines.
func (t *Terminal) SetPrompt(prompt string) {
t.lock.Lock()
defer t.lock.Unlock()
t.prompt = []rune(prompt)
}
func (t *Terminal) clearAndRepaintLinePlusNPrevious(numPrevLines int) {
// Move cursor to column zero at the start of the line.
t.move(t.cursorY, 0, t.cursorX, 0)
t.cursorX, t.cursorY = 0, 0
t.clearLineToRight()
for t.cursorY < numPrevLines {
// Move down a line
t.move(0, 1, 0, 0)
t.cursorY++
t.clearLineToRight()
}
// Move back to beginning.
t.move(t.cursorY, 0, 0, 0)
t.cursorX, t.cursorY = 0, 0
t.queue(t.prompt)
t.advanceCursor(visualLength(t.prompt))
t.writeLine(t.line)
t.moveCursorToPos(t.pos)
}
func (t *Terminal) SetSize(width, height int) error {
t.lock.Lock()
defer t.lock.Unlock()
if width == 0 {
width = 1
}
oldWidth := t.termWidth
t.termWidth, t.termHeight = width, height
switch {
case width == oldWidth:
// If the width didn't change then nothing else needs to be
// done.
return nil
case len(t.line) == 0 && t.cursorX == 0 && t.cursorY == 0:
// If there is nothing on current line and no prompt printed,
// just do nothing
return nil
case width < oldWidth:
// Some terminals (e.g. xterm) will truncate lines that were
// too long when shinking. Others, (e.g. gnome-terminal) will
// attempt to wrap them. For the former, repainting t.maxLine
// works great, but that behaviour goes badly wrong in the case
// of the latter because they have doubled every full line.
// We assume that we are working on a terminal that wraps lines
// and adjust the cursor position based on every previous line
// wrapping and turning into two. This causes the prompt on
// xterms to move upwards, which isn't great, but it avoids a
// huge mess with gnome-terminal.
if t.cursorX >= t.termWidth {
t.cursorX = t.termWidth - 1
}
t.cursorY *= 2
t.clearAndRepaintLinePlusNPrevious(t.maxLine * 2)
case width > oldWidth:
// If the terminal expands then our position calculations will
// be wrong in the future because we think the cursor is
// |t.pos| chars into the string, but there will be a gap at
// the end of any wrapped line.
//
// But the position will actually be correct until we move, so
// we can move back to the beginning and repaint everything.
t.clearAndRepaintLinePlusNPrevious(t.maxLine)
}
_, err := t.c.Write(t.outBuf)
t.outBuf = t.outBuf[:0]
return err
}
type pasteIndicatorError struct{}
func (pasteIndicatorError) Error() string {
return "terminal: ErrPasteIndicator not correctly handled"
}
// ErrPasteIndicator may be returned from ReadLine as the error, in addition
// to valid line data. It indicates that bracketed paste mode is enabled and
// that the returned line consists only of pasted data. Programs may wish to
// interpret pasted data more literally than typed data.
var ErrPasteIndicator = pasteIndicatorError{}
// SetBracketedPasteMode requests that the terminal bracket paste operations
// with markers. Not all terminals support this but, if it is supported, then
// enabling this mode will stop any autocomplete callback from running due to
// pastes. Additionally, any lines that are completely pasted will be returned
// from ReadLine with the error set to ErrPasteIndicator.
func (t *Terminal) SetBracketedPasteMode(on bool) {
if on {
io.WriteString(t.c, "\x1b[?2004h")
} else {
io.WriteString(t.c, "\x1b[?2004l")
}
}
// stRingBuffer is a ring buffer of strings.
type stRingBuffer struct {
// entries contains max elements.
entries []string
max int
// head contains the index of the element most recently added to the ring.
head int
// size contains the number of elements in the ring.
size int
}
func (s *stRingBuffer) Add(a string) {
if s.entries == nil {
const defaultNumEntries = 100
s.entries = make([]string, defaultNumEntries)
s.max = defaultNumEntries
}
s.head = (s.head + 1) % s.max
s.entries[s.head] = a
if s.size < s.max {
s.size++
}
}
// NthPreviousEntry returns the value passed to the nth previous call to Add.
// If n is zero then the immediately prior value is returned, if one, then the
// next most recent, and so on. If such an element doesn't exist then ok is
// false.
func (s *stRingBuffer) NthPreviousEntry(n int) (value string, ok bool) {
if n >= s.size {
return "", false
}
index := s.head - n
if index < 0 {
index += s.max
}
return s.entries[index], true
}
// readPasswordLine reads from reader until it finds \n or io.EOF.
// The slice returned does not include the \n.
// readPasswordLine also ignores any \r it finds.
func readPasswordLine(reader io.Reader) ([]byte, error) {
var buf [1]byte
var ret []byte
for {
n, err := reader.Read(buf[:])
if n > 0 {
switch buf[0] {
case '\n':
return ret, nil
case '\r':
// remove \r from passwords on Windows
default:
ret = append(ret, buf[0])
}
continue
}
if err != nil {
if err == io.EOF && len(ret) > 0 {
return ret, nil
}
return ret, err
}
}
}

View File

@@ -1,114 +0,0 @@
// 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.
// +build darwin dragonfly freebsd linux,!appengine netbsd openbsd
// Package terminal provides support functions for dealing with terminals, as
// commonly found on UNIX systems.
//
// Putting a terminal into raw mode is the most common requirement:
//
// oldState, err := terminal.MakeRaw(0)
// if err != nil {
// panic(err)
// }
// defer terminal.Restore(0, oldState)
package terminal // import "golang.org/x/crypto/ssh/terminal"
import (
"golang.org/x/sys/unix"
)
// State contains the state of a terminal.
type State struct {
termios unix.Termios
}
// IsTerminal returns true if the given file descriptor is a terminal.
func IsTerminal(fd int) bool {
_, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
return err == nil
}
// MakeRaw put the terminal connected to the given file descriptor into raw
// mode and returns the previous state of the terminal so that it can be
// restored.
func MakeRaw(fd int) (*State, error) {
termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
if err != nil {
return nil, err
}
oldState := State{termios: *termios}
// This attempts to replicate the behaviour documented for cfmakeraw in
// the termios(3) manpage.
termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON
termios.Oflag &^= unix.OPOST
termios.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN
termios.Cflag &^= unix.CSIZE | unix.PARENB
termios.Cflag |= unix.CS8
termios.Cc[unix.VMIN] = 1
termios.Cc[unix.VTIME] = 0
if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, termios); err != nil {
return nil, err
}
return &oldState, nil
}
// GetState returns the current state of a terminal which may be useful to
// restore the terminal after a signal.
func GetState(fd int) (*State, error) {
termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
if err != nil {
return nil, err
}
return &State{termios: *termios}, nil
}
// Restore restores the terminal connected to the given file descriptor to a
// previous state.
func Restore(fd int, state *State) error {
return unix.IoctlSetTermios(fd, ioctlWriteTermios, &state.termios)
}
// GetSize returns the dimensions of the given terminal.
func GetSize(fd int) (width, height int, err error) {
ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ)
if err != nil {
return -1, -1, err
}
return int(ws.Col), int(ws.Row), nil
}
// passwordReader is an io.Reader that reads from a specific file descriptor.
type passwordReader int
func (r passwordReader) Read(buf []byte) (int, error) {
return unix.Read(int(r), buf)
}
// ReadPassword reads a line of input from a terminal without local echo. This
// is commonly used for inputting passwords and other sensitive data. The slice
// returned does not include the \n.
func ReadPassword(fd int) ([]byte, error) {
termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
if err != nil {
return nil, err
}
newState := *termios
newState.Lflag &^= unix.ECHO
newState.Lflag |= unix.ICANON | unix.ISIG
newState.Iflag |= unix.ICRNL
if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, &newState); err != nil {
return nil, err
}
defer unix.IoctlSetTermios(fd, ioctlWriteTermios, termios)
return readPasswordLine(passwordReader(fd))
}

View File

@@ -1,58 +0,0 @@
// Copyright 2016 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 terminal provides support functions for dealing with terminals, as
// commonly found on UNIX systems.
//
// Putting a terminal into raw mode is the most common requirement:
//
// oldState, err := terminal.MakeRaw(0)
// if err != nil {
// panic(err)
// }
// defer terminal.Restore(0, oldState)
package terminal
import (
"fmt"
"runtime"
)
type State struct{}
// IsTerminal returns true if the given file descriptor is a terminal.
func IsTerminal(fd int) bool {
return false
}
// MakeRaw put the terminal connected to the given file descriptor into raw
// mode and returns the previous state of the terminal so that it can be
// restored.
func MakeRaw(fd int) (*State, error) {
return nil, fmt.Errorf("terminal: MakeRaw not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
}
// GetState returns the current state of a terminal which may be useful to
// restore the terminal after a signal.
func GetState(fd int) (*State, error) {
return nil, fmt.Errorf("terminal: GetState not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
}
// Restore restores the terminal connected to the given file descriptor to a
// previous state.
func Restore(fd int, state *State) error {
return fmt.Errorf("terminal: Restore not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
}
// GetSize returns the dimensions of the given terminal.
func GetSize(fd int) (width, height int, err error) {
return 0, 0, fmt.Errorf("terminal: GetSize not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
}
// ReadPassword reads a line of input from a terminal without local echo. This
// is commonly used for inputting passwords and other sensitive data. The slice
// returned does not include the \n.
func ReadPassword(fd int) ([]byte, error) {
return nil, fmt.Errorf("terminal: ReadPassword not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
}

View File

@@ -1,124 +0,0 @@
// Copyright 2015 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.
// +build solaris
package terminal // import "golang.org/x/crypto/ssh/terminal"
import (
"golang.org/x/sys/unix"
"io"
"syscall"
)
// State contains the state of a terminal.
type State struct {
termios unix.Termios
}
// IsTerminal returns true if the given file descriptor is a terminal.
func IsTerminal(fd int) bool {
_, err := unix.IoctlGetTermio(fd, unix.TCGETA)
return err == nil
}
// ReadPassword reads a line of input from a terminal without local echo. This
// is commonly used for inputting passwords and other sensitive data. The slice
// returned does not include the \n.
func ReadPassword(fd int) ([]byte, error) {
// see also: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libast/common/uwin/getpass.c
val, err := unix.IoctlGetTermios(fd, unix.TCGETS)
if err != nil {
return nil, err
}
oldState := *val
newState := oldState
newState.Lflag &^= syscall.ECHO
newState.Lflag |= syscall.ICANON | syscall.ISIG
newState.Iflag |= syscall.ICRNL
err = unix.IoctlSetTermios(fd, unix.TCSETS, &newState)
if err != nil {
return nil, err
}
defer unix.IoctlSetTermios(fd, unix.TCSETS, &oldState)
var buf [16]byte
var ret []byte
for {
n, err := syscall.Read(fd, buf[:])
if err != nil {
return nil, err
}
if n == 0 {
if len(ret) == 0 {
return nil, io.EOF
}
break
}
if buf[n-1] == '\n' {
n--
}
ret = append(ret, buf[:n]...)
if n < len(buf) {
break
}
}
return ret, nil
}
// MakeRaw puts the terminal connected to the given file descriptor into raw
// mode and returns the previous state of the terminal so that it can be
// restored.
// see http://cr.illumos.org/~webrev/andy_js/1060/
func MakeRaw(fd int) (*State, error) {
termios, err := unix.IoctlGetTermios(fd, unix.TCGETS)
if err != nil {
return nil, err
}
oldState := State{termios: *termios}
termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON
termios.Oflag &^= unix.OPOST
termios.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN
termios.Cflag &^= unix.CSIZE | unix.PARENB
termios.Cflag |= unix.CS8
termios.Cc[unix.VMIN] = 1
termios.Cc[unix.VTIME] = 0
if err := unix.IoctlSetTermios(fd, unix.TCSETS, termios); err != nil {
return nil, err
}
return &oldState, nil
}
// Restore restores the terminal connected to the given file descriptor to a
// previous state.
func Restore(fd int, oldState *State) error {
return unix.IoctlSetTermios(fd, unix.TCSETS, &oldState.termios)
}
// GetState returns the current state of a terminal which may be useful to
// restore the terminal after a signal.
func GetState(fd int) (*State, error) {
termios, err := unix.IoctlGetTermios(fd, unix.TCGETS)
if err != nil {
return nil, err
}
return &State{termios: *termios}, nil
}
// GetSize returns the dimensions of the given terminal.
func GetSize(fd int) (width, height int, err error) {
ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ)
if err != nil {
return 0, 0, err
}
return int(ws.Col), int(ws.Row), nil
}

View File

@@ -1,103 +0,0 @@
// 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.
// +build windows
// Package terminal provides support functions for dealing with terminals, as
// commonly found on UNIX systems.
//
// Putting a terminal into raw mode is the most common requirement:
//
// oldState, err := terminal.MakeRaw(0)
// if err != nil {
// panic(err)
// }
// defer terminal.Restore(0, oldState)
package terminal
import (
"os"
"golang.org/x/sys/windows"
)
type State struct {
mode uint32
}
// IsTerminal returns true if the given file descriptor is a terminal.
func IsTerminal(fd int) bool {
var st uint32
err := windows.GetConsoleMode(windows.Handle(fd), &st)
return err == nil
}
// MakeRaw put the terminal connected to the given file descriptor into raw
// mode and returns the previous state of the terminal so that it can be
// restored.
func MakeRaw(fd int) (*State, error) {
var st uint32
if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
return nil, err
}
raw := st &^ (windows.ENABLE_ECHO_INPUT | windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT)
if err := windows.SetConsoleMode(windows.Handle(fd), raw); err != nil {
return nil, err
}
return &State{st}, nil
}
// GetState returns the current state of a terminal which may be useful to
// restore the terminal after a signal.
func GetState(fd int) (*State, error) {
var st uint32
if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
return nil, err
}
return &State{st}, nil
}
// Restore restores the terminal connected to the given file descriptor to a
// previous state.
func Restore(fd int, state *State) error {
return windows.SetConsoleMode(windows.Handle(fd), state.mode)
}
// GetSize returns the dimensions of the given terminal.
func GetSize(fd int) (width, height int, err error) {
var info windows.ConsoleScreenBufferInfo
if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil {
return 0, 0, err
}
return int(info.Size.X), int(info.Size.Y), nil
}
// ReadPassword reads a line of input from a terminal without local echo. This
// is commonly used for inputting passwords and other sensitive data. The slice
// returned does not include the \n.
func ReadPassword(fd int) ([]byte, error) {
var st uint32
if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
return nil, err
}
old := st
st &^= (windows.ENABLE_ECHO_INPUT)
st |= (windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT)
if err := windows.SetConsoleMode(windows.Handle(fd), st); err != nil {
return nil, err
}
defer windows.SetConsoleMode(windows.Handle(fd), old)
var h windows.Handle
p, _ := windows.GetCurrentProcess()
if err := windows.DuplicateHandle(p, windows.Handle(fd), p, &h, 0, false, windows.DUPLICATE_SAME_ACCESS); err != nil {
return nil, err
}
f := os.NewFile(uintptr(h), "stdin")
defer f.Close()
return readPasswordLine(f)
}

View File

@@ -1,56 +0,0 @@
// Copyright 2014 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 context defines the Context type, which carries deadlines,
// cancelation signals, and other request-scoped values across API boundaries
// and between processes.
// As of Go 1.7 this package is available in the standard library under the
// name context. https://golang.org/pkg/context.
//
// Incoming requests to a server should create a Context, and outgoing calls to
// servers should accept a Context. The chain of function calls between must
// propagate the Context, optionally replacing it with a modified copy created
// using WithDeadline, WithTimeout, WithCancel, or WithValue.
//
// Programs that use Contexts should follow these rules to keep interfaces
// consistent across packages and enable static analysis tools to check context
// propagation:
//
// Do not store Contexts inside a struct type; instead, pass a Context
// explicitly to each function that needs it. The Context should be the first
// parameter, typically named ctx:
//
// func DoSomething(ctx context.Context, arg Arg) error {
// // ... use ctx ...
// }
//
// Do not pass a nil Context, even if a function permits it. Pass context.TODO
// if you are unsure about which Context to use.
//
// Use context Values only for request-scoped data that transits processes and
// APIs, not for passing optional parameters to functions.
//
// The same Context may be passed to functions running in different goroutines;
// Contexts are safe for simultaneous use by multiple goroutines.
//
// See http://blog.golang.org/context for example code for a server that uses
// Contexts.
package context // import "golang.org/x/net/context"
// Background returns a non-nil, empty Context. It is never canceled, has no
// values, and has no deadline. It is typically used by the main function,
// initialization, and tests, and as the top-level Context for incoming
// requests.
func Background() Context {
return background
}
// TODO returns a non-nil, empty Context. Code should use context.TODO when
// it's unclear which Context to use or it is not yet available (because the
// surrounding function has not yet been extended to accept a Context
// parameter). TODO is recognized by static analysis tools that determine
// whether Contexts are propagated correctly in a program.
func TODO() Context {
return todo
}

View File

@@ -1,72 +0,0 @@
// Copyright 2016 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.
// +build go1.7
package context
import (
"context" // standard library's context, as of Go 1.7
"time"
)
var (
todo = context.TODO()
background = context.Background()
)
// Canceled is the error returned by Context.Err when the context is canceled.
var Canceled = context.Canceled
// DeadlineExceeded is the error returned by Context.Err when the context's
// deadline passes.
var DeadlineExceeded = context.DeadlineExceeded
// WithCancel returns a copy of parent with a new Done channel. The returned
// context's Done channel is closed when the returned cancel function is called
// or when the parent context's Done channel is closed, whichever happens first.
//
// Canceling this context releases resources associated with it, so code should
// call cancel as soon as the operations running in this Context complete.
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
ctx, f := context.WithCancel(parent)
return ctx, CancelFunc(f)
}
// WithDeadline returns a copy of the parent context with the deadline adjusted
// to be no later than d. If the parent's deadline is already earlier than d,
// WithDeadline(parent, d) is semantically equivalent to parent. The returned
// context's Done channel is closed when the deadline expires, when the returned
// cancel function is called, or when the parent context's Done channel is
// closed, whichever happens first.
//
// Canceling this context releases resources associated with it, so code should
// call cancel as soon as the operations running in this Context complete.
func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
ctx, f := context.WithDeadline(parent, deadline)
return ctx, CancelFunc(f)
}
// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
//
// Canceling this context releases resources associated with it, so code should
// call cancel as soon as the operations running in this Context complete:
//
// func slowOperationWithTimeout(ctx context.Context) (Result, error) {
// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
// defer cancel() // releases resources if slowOperation completes before timeout elapses
// return slowOperation(ctx)
// }
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
return WithDeadline(parent, time.Now().Add(timeout))
}
// WithValue returns a copy of parent in which the value associated with key is
// val.
//
// Use context Values only for request-scoped data that transits processes and
// APIs, not for passing optional parameters to functions.
func WithValue(parent Context, key interface{}, val interface{}) Context {
return context.WithValue(parent, key, val)
}

View File

@@ -1,20 +0,0 @@
// 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.
// +build go1.9
package context
import "context" // standard library's context, as of Go 1.7
// A Context carries a deadline, a cancelation signal, and other values across
// API boundaries.
//
// Context's methods may be called by multiple goroutines simultaneously.
type Context = context.Context
// A CancelFunc tells an operation to abandon its work.
// A CancelFunc does not wait for the work to stop.
// After the first call, subsequent calls to a CancelFunc do nothing.
type CancelFunc = context.CancelFunc

View File

@@ -1,300 +0,0 @@
// Copyright 2014 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.
// +build !go1.7
package context
import (
"errors"
"fmt"
"sync"
"time"
)
// An emptyCtx is never canceled, has no values, and has no deadline. It is not
// struct{}, since vars of this type must have distinct addresses.
type emptyCtx int
func (*emptyCtx) Deadline() (deadline time.Time, ok bool) {
return
}
func (*emptyCtx) Done() <-chan struct{} {
return nil
}
func (*emptyCtx) Err() error {
return nil
}
func (*emptyCtx) Value(key interface{}) interface{} {
return nil
}
func (e *emptyCtx) String() string {
switch e {
case background:
return "context.Background"
case todo:
return "context.TODO"
}
return "unknown empty Context"
}
var (
background = new(emptyCtx)
todo = new(emptyCtx)
)
// Canceled is the error returned by Context.Err when the context is canceled.
var Canceled = errors.New("context canceled")
// DeadlineExceeded is the error returned by Context.Err when the context's
// deadline passes.
var DeadlineExceeded = errors.New("context deadline exceeded")
// WithCancel returns a copy of parent with a new Done channel. The returned
// context's Done channel is closed when the returned cancel function is called
// or when the parent context's Done channel is closed, whichever happens first.
//
// Canceling this context releases resources associated with it, so code should
// call cancel as soon as the operations running in this Context complete.
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
c := newCancelCtx(parent)
propagateCancel(parent, c)
return c, func() { c.cancel(true, Canceled) }
}
// newCancelCtx returns an initialized cancelCtx.
func newCancelCtx(parent Context) *cancelCtx {
return &cancelCtx{
Context: parent,
done: make(chan struct{}),
}
}
// propagateCancel arranges for child to be canceled when parent is.
func propagateCancel(parent Context, child canceler) {
if parent.Done() == nil {
return // parent is never canceled
}
if p, ok := parentCancelCtx(parent); ok {
p.mu.Lock()
if p.err != nil {
// parent has already been canceled
child.cancel(false, p.err)
} else {
if p.children == nil {
p.children = make(map[canceler]bool)
}
p.children[child] = true
}
p.mu.Unlock()
} else {
go func() {
select {
case <-parent.Done():
child.cancel(false, parent.Err())
case <-child.Done():
}
}()
}
}
// parentCancelCtx follows a chain of parent references until it finds a
// *cancelCtx. This function understands how each of the concrete types in this
// package represents its parent.
func parentCancelCtx(parent Context) (*cancelCtx, bool) {
for {
switch c := parent.(type) {
case *cancelCtx:
return c, true
case *timerCtx:
return c.cancelCtx, true
case *valueCtx:
parent = c.Context
default:
return nil, false
}
}
}
// removeChild removes a context from its parent.
func removeChild(parent Context, child canceler) {
p, ok := parentCancelCtx(parent)
if !ok {
return
}
p.mu.Lock()
if p.children != nil {
delete(p.children, child)
}
p.mu.Unlock()
}
// A canceler is a context type that can be canceled directly. The
// implementations are *cancelCtx and *timerCtx.
type canceler interface {
cancel(removeFromParent bool, err error)
Done() <-chan struct{}
}
// A cancelCtx can be canceled. When canceled, it also cancels any children
// that implement canceler.
type cancelCtx struct {
Context
done chan struct{} // closed by the first cancel call.
mu sync.Mutex
children map[canceler]bool // set to nil by the first cancel call
err error // set to non-nil by the first cancel call
}
func (c *cancelCtx) Done() <-chan struct{} {
return c.done
}
func (c *cancelCtx) Err() error {
c.mu.Lock()
defer c.mu.Unlock()
return c.err
}
func (c *cancelCtx) String() string {
return fmt.Sprintf("%v.WithCancel", c.Context)
}
// cancel closes c.done, cancels each of c's children, and, if
// removeFromParent is true, removes c from its parent's children.
func (c *cancelCtx) cancel(removeFromParent bool, err error) {
if err == nil {
panic("context: internal error: missing cancel error")
}
c.mu.Lock()
if c.err != nil {
c.mu.Unlock()
return // already canceled
}
c.err = err
close(c.done)
for child := range c.children {
// NOTE: acquiring the child's lock while holding parent's lock.
child.cancel(false, err)
}
c.children = nil
c.mu.Unlock()
if removeFromParent {
removeChild(c.Context, c)
}
}
// WithDeadline returns a copy of the parent context with the deadline adjusted
// to be no later than d. If the parent's deadline is already earlier than d,
// WithDeadline(parent, d) is semantically equivalent to parent. The returned
// context's Done channel is closed when the deadline expires, when the returned
// cancel function is called, or when the parent context's Done channel is
// closed, whichever happens first.
//
// Canceling this context releases resources associated with it, so code should
// call cancel as soon as the operations running in this Context complete.
func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
if cur, ok := parent.Deadline(); ok && cur.Before(deadline) {
// The current deadline is already sooner than the new one.
return WithCancel(parent)
}
c := &timerCtx{
cancelCtx: newCancelCtx(parent),
deadline: deadline,
}
propagateCancel(parent, c)
d := deadline.Sub(time.Now())
if d <= 0 {
c.cancel(true, DeadlineExceeded) // deadline has already passed
return c, func() { c.cancel(true, Canceled) }
}
c.mu.Lock()
defer c.mu.Unlock()
if c.err == nil {
c.timer = time.AfterFunc(d, func() {
c.cancel(true, DeadlineExceeded)
})
}
return c, func() { c.cancel(true, Canceled) }
}
// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to
// implement Done and Err. It implements cancel by stopping its timer then
// delegating to cancelCtx.cancel.
type timerCtx struct {
*cancelCtx
timer *time.Timer // Under cancelCtx.mu.
deadline time.Time
}
func (c *timerCtx) Deadline() (deadline time.Time, ok bool) {
return c.deadline, true
}
func (c *timerCtx) String() string {
return fmt.Sprintf("%v.WithDeadline(%s [%s])", c.cancelCtx.Context, c.deadline, c.deadline.Sub(time.Now()))
}
func (c *timerCtx) cancel(removeFromParent bool, err error) {
c.cancelCtx.cancel(false, err)
if removeFromParent {
// Remove this timerCtx from its parent cancelCtx's children.
removeChild(c.cancelCtx.Context, c)
}
c.mu.Lock()
if c.timer != nil {
c.timer.Stop()
c.timer = nil
}
c.mu.Unlock()
}
// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
//
// Canceling this context releases resources associated with it, so code should
// call cancel as soon as the operations running in this Context complete:
//
// func slowOperationWithTimeout(ctx context.Context) (Result, error) {
// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
// defer cancel() // releases resources if slowOperation completes before timeout elapses
// return slowOperation(ctx)
// }
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
return WithDeadline(parent, time.Now().Add(timeout))
}
// WithValue returns a copy of parent in which the value associated with key is
// val.
//
// Use context Values only for request-scoped data that transits processes and
// APIs, not for passing optional parameters to functions.
func WithValue(parent Context, key interface{}, val interface{}) Context {
return &valueCtx{parent, key, val}
}
// A valueCtx carries a key-value pair. It implements Value for that key and
// delegates all other calls to the embedded Context.
type valueCtx struct {
Context
key, val interface{}
}
func (c *valueCtx) String() string {
return fmt.Sprintf("%v.WithValue(%#v, %#v)", c.Context, c.key, c.val)
}
func (c *valueCtx) Value(key interface{}) interface{} {
if c.key == key {
return c.val
}
return c.Context.Value(key)
}

View File

@@ -1,109 +0,0 @@
// Copyright 2014 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.
// +build !go1.9
package context
import "time"
// A Context carries a deadline, a cancelation signal, and other values across
// API boundaries.
//
// Context's methods may be called by multiple goroutines simultaneously.
type Context interface {
// Deadline returns the time when work done on behalf of this context
// should be canceled. Deadline returns ok==false when no deadline is
// set. Successive calls to Deadline return the same results.
Deadline() (deadline time.Time, ok bool)
// Done returns a channel that's closed when work done on behalf of this
// context should be canceled. Done may return nil if this context can
// never be canceled. Successive calls to Done return the same value.
//
// WithCancel arranges for Done to be closed when cancel is called;
// WithDeadline arranges for Done to be closed when the deadline
// expires; WithTimeout arranges for Done to be closed when the timeout
// elapses.
//
// Done is provided for use in select statements:
//
// // Stream generates values with DoSomething and sends them to out
// // until DoSomething returns an error or ctx.Done is closed.
// func Stream(ctx context.Context, out chan<- Value) error {
// for {
// v, err := DoSomething(ctx)
// if err != nil {
// return err
// }
// select {
// case <-ctx.Done():
// return ctx.Err()
// case out <- v:
// }
// }
// }
//
// See http://blog.golang.org/pipelines for more examples of how to use
// a Done channel for cancelation.
Done() <-chan struct{}
// Err returns a non-nil error value after Done is closed. Err returns
// Canceled if the context was canceled or DeadlineExceeded if the
// context's deadline passed. No other values for Err are defined.
// After Done is closed, successive calls to Err return the same value.
Err() error
// Value returns the value associated with this context for key, or nil
// if no value is associated with key. Successive calls to Value with
// the same key returns the same result.
//
// Use context values only for request-scoped data that transits
// processes and API boundaries, not for passing optional parameters to
// functions.
//
// A key identifies a specific value in a Context. Functions that wish
// to store values in Context typically allocate a key in a global
// variable then use that key as the argument to context.WithValue and
// Context.Value. A key can be any type that supports equality;
// packages should define keys as an unexported type to avoid
// collisions.
//
// Packages that define a Context key should provide type-safe accessors
// for the values stores using that key:
//
// // Package user defines a User type that's stored in Contexts.
// package user
//
// import "golang.org/x/net/context"
//
// // User is the type of value stored in the Contexts.
// type User struct {...}
//
// // key is an unexported type for keys defined in this package.
// // This prevents collisions with keys defined in other packages.
// type key int
//
// // userKey is the key for user.User values in Contexts. It is
// // unexported; clients use user.NewContext and user.FromContext
// // instead of using this key directly.
// var userKey key = 0
//
// // NewContext returns a new Context that carries value u.
// func NewContext(ctx context.Context, u *User) context.Context {
// return context.WithValue(ctx, userKey, u)
// }
//
// // FromContext returns the User value stored in ctx, if any.
// func FromContext(ctx context.Context) (*User, bool) {
// u, ok := ctx.Value(userKey).(*User)
// return u, ok
// }
Value(key interface{}) interface{}
}
// A CancelFunc tells an operation to abandon its work.
// A CancelFunc does not wait for the work to stop.
// After the first call, subsequent calls to a CancelFunc do nothing.
type CancelFunc func()

View File

@@ -7,9 +7,8 @@
package errgroup
import (
"context"
"sync"
"golang.org/x/net/context"
)
// A Group is a collection of goroutines working on subtasks that are part of

8
vendor/golang.org/x/sys/plan9/asm.s generated vendored Normal file
View File

@@ -0,0 +1,8 @@
// Copyright 2014 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.
#include "textflag.h"
TEXT ·use(SB),NOSPLIT,$0
RET

30
vendor/golang.org/x/sys/plan9/asm_plan9_386.s generated vendored Normal file
View File

@@ -0,0 +1,30 @@
// Copyright 2009 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.
#include "textflag.h"
//
// System call support for 386, Plan 9
//
// Just jump to package syscall's implementation for all these functions.
// The runtime may know about them.
TEXT ·Syscall(SB),NOSPLIT,$0-32
JMP syscall·Syscall(SB)
TEXT ·Syscall6(SB),NOSPLIT,$0-44
JMP syscall·Syscall6(SB)
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
JMP syscall·RawSyscall(SB)
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
JMP syscall·RawSyscall6(SB)
TEXT ·seek(SB),NOSPLIT,$0-36
JMP syscall·seek(SB)
TEXT ·exit(SB),NOSPLIT,$4-4
JMP syscall·exit(SB)

30
vendor/golang.org/x/sys/plan9/asm_plan9_amd64.s generated vendored Normal file
View File

@@ -0,0 +1,30 @@
// Copyright 2009 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.
#include "textflag.h"
//
// System call support for amd64, Plan 9
//
// Just jump to package syscall's implementation for all these functions.
// The runtime may know about them.
TEXT ·Syscall(SB),NOSPLIT,$0-64
JMP syscall·Syscall(SB)
TEXT ·Syscall6(SB),NOSPLIT,$0-88
JMP syscall·Syscall6(SB)
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
JMP syscall·RawSyscall(SB)
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
JMP syscall·RawSyscall6(SB)
TEXT ·seek(SB),NOSPLIT,$0-56
JMP syscall·seek(SB)
TEXT ·exit(SB),NOSPLIT,$8-8
JMP syscall·exit(SB)

25
vendor/golang.org/x/sys/plan9/asm_plan9_arm.s generated vendored Normal file
View File

@@ -0,0 +1,25 @@
// Copyright 2009 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.
#include "textflag.h"
// System call support for plan9 on arm
// Just jump to package syscall's implementation for all these functions.
// The runtime may know about them.
TEXT ·Syscall(SB),NOSPLIT,$0-32
JMP syscall·Syscall(SB)
TEXT ·Syscall6(SB),NOSPLIT,$0-44
JMP syscall·Syscall6(SB)
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
JMP syscall·RawSyscall(SB)
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
JMP syscall·RawSyscall6(SB)
TEXT ·seek(SB),NOSPLIT,$0-36
JMP syscall·exit(SB)

70
vendor/golang.org/x/sys/plan9/const_plan9.go generated vendored Normal file
View File

@@ -0,0 +1,70 @@
package plan9
// Plan 9 Constants
// Open modes
const (
O_RDONLY = 0
O_WRONLY = 1
O_RDWR = 2
O_TRUNC = 16
O_CLOEXEC = 32
O_EXCL = 0x1000
)
// Rfork flags
const (
RFNAMEG = 1 << 0
RFENVG = 1 << 1
RFFDG = 1 << 2
RFNOTEG = 1 << 3
RFPROC = 1 << 4
RFMEM = 1 << 5
RFNOWAIT = 1 << 6
RFCNAMEG = 1 << 10
RFCENVG = 1 << 11
RFCFDG = 1 << 12
RFREND = 1 << 13
RFNOMNT = 1 << 14
)
// Qid.Type bits
const (
QTDIR = 0x80
QTAPPEND = 0x40
QTEXCL = 0x20
QTMOUNT = 0x10
QTAUTH = 0x08
QTTMP = 0x04
QTFILE = 0x00
)
// Dir.Mode bits
const (
DMDIR = 0x80000000
DMAPPEND = 0x40000000
DMEXCL = 0x20000000
DMMOUNT = 0x10000000
DMAUTH = 0x08000000
DMTMP = 0x04000000
DMREAD = 0x4
DMWRITE = 0x2
DMEXEC = 0x1
)
const (
STATMAX = 65535
ERRMAX = 128
STATFIXLEN = 49
)
// Mount and bind flags
const (
MREPL = 0x0000
MBEFORE = 0x0001
MAFTER = 0x0002
MORDER = 0x0003
MCREATE = 0x0004
MCACHE = 0x0010
MMASK = 0x0017
)

212
vendor/golang.org/x/sys/plan9/dir_plan9.go generated vendored Normal file
View File

@@ -0,0 +1,212 @@
// 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.
// Plan 9 directory marshalling. See intro(5).
package plan9
import "errors"
var (
ErrShortStat = errors.New("stat buffer too short")
ErrBadStat = errors.New("malformed stat buffer")
ErrBadName = errors.New("bad character in file name")
)
// A Qid represents a 9P server's unique identification for a file.
type Qid struct {
Path uint64 // the file server's unique identification for the file
Vers uint32 // version number for given Path
Type uint8 // the type of the file (plan9.QTDIR for example)
}
// A Dir contains the metadata for a file.
type Dir struct {
// system-modified data
Type uint16 // server type
Dev uint32 // server subtype
// file data
Qid Qid // unique id from server
Mode uint32 // permissions
Atime uint32 // last read time
Mtime uint32 // last write time
Length int64 // file length
Name string // last element of path
Uid string // owner name
Gid string // group name
Muid string // last modifier name
}
var nullDir = Dir{
Type: ^uint16(0),
Dev: ^uint32(0),
Qid: Qid{
Path: ^uint64(0),
Vers: ^uint32(0),
Type: ^uint8(0),
},
Mode: ^uint32(0),
Atime: ^uint32(0),
Mtime: ^uint32(0),
Length: ^int64(0),
}
// Null assigns special "don't touch" values to members of d to
// avoid modifying them during plan9.Wstat.
func (d *Dir) Null() { *d = nullDir }
// Marshal encodes a 9P stat message corresponding to d into b
//
// If there isn't enough space in b for a stat message, ErrShortStat is returned.
func (d *Dir) Marshal(b []byte) (n int, err error) {
n = STATFIXLEN + len(d.Name) + len(d.Uid) + len(d.Gid) + len(d.Muid)
if n > len(b) {
return n, ErrShortStat
}
for _, c := range d.Name {
if c == '/' {
return n, ErrBadName
}
}
b = pbit16(b, uint16(n)-2)
b = pbit16(b, d.Type)
b = pbit32(b, d.Dev)
b = pbit8(b, d.Qid.Type)
b = pbit32(b, d.Qid.Vers)
b = pbit64(b, d.Qid.Path)
b = pbit32(b, d.Mode)
b = pbit32(b, d.Atime)
b = pbit32(b, d.Mtime)
b = pbit64(b, uint64(d.Length))
b = pstring(b, d.Name)
b = pstring(b, d.Uid)
b = pstring(b, d.Gid)
b = pstring(b, d.Muid)
return n, nil
}
// UnmarshalDir decodes a single 9P stat message from b and returns the resulting Dir.
//
// If b is too small to hold a valid stat message, ErrShortStat is returned.
//
// If the stat message itself is invalid, ErrBadStat is returned.
func UnmarshalDir(b []byte) (*Dir, error) {
if len(b) < STATFIXLEN {
return nil, ErrShortStat
}
size, buf := gbit16(b)
if len(b) != int(size)+2 {
return nil, ErrBadStat
}
b = buf
var d Dir
d.Type, b = gbit16(b)
d.Dev, b = gbit32(b)
d.Qid.Type, b = gbit8(b)
d.Qid.Vers, b = gbit32(b)
d.Qid.Path, b = gbit64(b)
d.Mode, b = gbit32(b)
d.Atime, b = gbit32(b)
d.Mtime, b = gbit32(b)
n, b := gbit64(b)
d.Length = int64(n)
var ok bool
if d.Name, b, ok = gstring(b); !ok {
return nil, ErrBadStat
}
if d.Uid, b, ok = gstring(b); !ok {
return nil, ErrBadStat
}
if d.Gid, b, ok = gstring(b); !ok {
return nil, ErrBadStat
}
if d.Muid, b, ok = gstring(b); !ok {
return nil, ErrBadStat
}
return &d, nil
}
// pbit8 copies the 8-bit number v to b and returns the remaining slice of b.
func pbit8(b []byte, v uint8) []byte {
b[0] = byte(v)
return b[1:]
}
// pbit16 copies the 16-bit number v to b in little-endian order and returns the remaining slice of b.
func pbit16(b []byte, v uint16) []byte {
b[0] = byte(v)
b[1] = byte(v >> 8)
return b[2:]
}
// pbit32 copies the 32-bit number v to b in little-endian order and returns the remaining slice of b.
func pbit32(b []byte, v uint32) []byte {
b[0] = byte(v)
b[1] = byte(v >> 8)
b[2] = byte(v >> 16)
b[3] = byte(v >> 24)
return b[4:]
}
// pbit64 copies the 64-bit number v to b in little-endian order and returns the remaining slice of b.
func pbit64(b []byte, v uint64) []byte {
b[0] = byte(v)
b[1] = byte(v >> 8)
b[2] = byte(v >> 16)
b[3] = byte(v >> 24)
b[4] = byte(v >> 32)
b[5] = byte(v >> 40)
b[6] = byte(v >> 48)
b[7] = byte(v >> 56)
return b[8:]
}
// pstring copies the string s to b, prepending it with a 16-bit length in little-endian order, and
// returning the remaining slice of b..
func pstring(b []byte, s string) []byte {
b = pbit16(b, uint16(len(s)))
n := copy(b, s)
return b[n:]
}
// gbit8 reads an 8-bit number from b and returns it with the remaining slice of b.
func gbit8(b []byte) (uint8, []byte) {
return uint8(b[0]), b[1:]
}
// gbit16 reads a 16-bit number in little-endian order from b and returns it with the remaining slice of b.
func gbit16(b []byte) (uint16, []byte) {
return uint16(b[0]) | uint16(b[1])<<8, b[2:]
}
// gbit32 reads a 32-bit number in little-endian order from b and returns it with the remaining slice of b.
func gbit32(b []byte) (uint32, []byte) {
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24, b[4:]
}
// gbit64 reads a 64-bit number in little-endian order from b and returns it with the remaining slice of b.
func gbit64(b []byte) (uint64, []byte) {
lo := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
hi := uint32(b[4]) | uint32(b[5])<<8 | uint32(b[6])<<16 | uint32(b[7])<<24
return uint64(lo) | uint64(hi)<<32, b[8:]
}
// gstring reads a string from b, prefixed with a 16-bit length in little-endian order.
// It returns the string with the remaining slice of b and a boolean. If the length is
// greater than the number of bytes in b, the boolean will be false.
func gstring(b []byte) (string, []byte, bool) {
n, b := gbit16(b)
if int(n) > len(b) {
return "", b, false
}
return string(b[:n]), b[n:], true
}

31
vendor/golang.org/x/sys/plan9/env_plan9.go generated vendored Normal file
View File

@@ -0,0 +1,31 @@
// 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.
// Plan 9 environment variables.
package plan9
import (
"syscall"
)
func Getenv(key string) (value string, found bool) {
return syscall.Getenv(key)
}
func Setenv(key, value string) error {
return syscall.Setenv(key, value)
}
func Clearenv() {
syscall.Clearenv()
}
func Environ() []string {
return syscall.Environ()
}
func Unsetenv(key string) error {
return syscall.Unsetenv(key)
}

50
vendor/golang.org/x/sys/plan9/errors_plan9.go generated vendored Normal file
View File

@@ -0,0 +1,50 @@
// 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 plan9
import "syscall"
// Constants
const (
// Invented values to support what package os expects.
O_CREAT = 0x02000
O_APPEND = 0x00400
O_NOCTTY = 0x00000
O_NONBLOCK = 0x00000
O_SYNC = 0x00000
O_ASYNC = 0x00000
S_IFMT = 0x1f000
S_IFIFO = 0x1000
S_IFCHR = 0x2000
S_IFDIR = 0x4000
S_IFBLK = 0x6000
S_IFREG = 0x8000
S_IFLNK = 0xa000
S_IFSOCK = 0xc000
)
// Errors
var (
EINVAL = syscall.NewError("bad arg in system call")
ENOTDIR = syscall.NewError("not a directory")
EISDIR = syscall.NewError("file is a directory")
ENOENT = syscall.NewError("file does not exist")
EEXIST = syscall.NewError("file already exists")
EMFILE = syscall.NewError("no free file descriptors")
EIO = syscall.NewError("i/o error")
ENAMETOOLONG = syscall.NewError("file name too long")
EINTR = syscall.NewError("interrupted")
EPERM = syscall.NewError("permission denied")
EBUSY = syscall.NewError("no free devices")
ETIMEDOUT = syscall.NewError("connection timed out")
EPLAN9 = syscall.NewError("not supported by plan 9")
// The following errors do not correspond to any
// Plan 9 system messages. Invented to support
// what package os and others expect.
EACCES = syscall.NewError("access permission denied")
EAFNOSUPPORT = syscall.NewError("address family not supported by protocol")
)

150
vendor/golang.org/x/sys/plan9/mkall.sh generated vendored Normal file
View File

@@ -0,0 +1,150 @@
#!/usr/bin/env bash
# Copyright 2009 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.
# The plan9 package provides access to the raw system call
# interface of the underlying operating system. Porting Go to
# a new architecture/operating system combination requires
# some manual effort, though there are tools that automate
# much of the process. The auto-generated files have names
# beginning with z.
#
# This script runs or (given -n) prints suggested commands to generate z files
# for the current system. Running those commands is not automatic.
# This script is documentation more than anything else.
#
# * asm_${GOOS}_${GOARCH}.s
#
# This hand-written assembly file implements system call dispatch.
# There are three entry points:
#
# func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr);
# func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr);
# func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr);
#
# The first and second are the standard ones; they differ only in
# how many arguments can be passed to the kernel.
# The third is for low-level use by the ForkExec wrapper;
# unlike the first two, it does not call into the scheduler to
# let it know that a system call is running.
#
# * syscall_${GOOS}.go
#
# This hand-written Go file implements system calls that need
# special handling and lists "//sys" comments giving prototypes
# for ones that can be auto-generated. Mksyscall reads those
# comments to generate the stubs.
#
# * syscall_${GOOS}_${GOARCH}.go
#
# Same as syscall_${GOOS}.go except that it contains code specific
# to ${GOOS} on one particular architecture.
#
# * types_${GOOS}.c
#
# This hand-written C file includes standard C headers and then
# creates typedef or enum names beginning with a dollar sign
# (use of $ in variable names is a gcc extension). The hardest
# part about preparing this file is figuring out which headers to
# include and which symbols need to be #defined to get the
# actual data structures that pass through to the kernel system calls.
# Some C libraries present alternate versions for binary compatibility
# and translate them on the way in and out of system calls, but
# there is almost always a #define that can get the real ones.
# See types_darwin.c and types_linux.c for examples.
#
# * zerror_${GOOS}_${GOARCH}.go
#
# This machine-generated file defines the system's error numbers,
# error strings, and signal numbers. The generator is "mkerrors.sh".
# Usually no arguments are needed, but mkerrors.sh will pass its
# arguments on to godefs.
#
# * zsyscall_${GOOS}_${GOARCH}.go
#
# Generated by mksyscall.pl; see syscall_${GOOS}.go above.
#
# * zsysnum_${GOOS}_${GOARCH}.go
#
# Generated by mksysnum_${GOOS}.
#
# * ztypes_${GOOS}_${GOARCH}.go
#
# Generated by godefs; see types_${GOOS}.c above.
GOOSARCH="${GOOS}_${GOARCH}"
# defaults
mksyscall="go run mksyscall.go"
mkerrors="./mkerrors.sh"
zerrors="zerrors_$GOOSARCH.go"
mksysctl=""
zsysctl="zsysctl_$GOOSARCH.go"
mksysnum=
mktypes=
run="sh"
case "$1" in
-syscalls)
for i in zsyscall*go
do
sed 1q $i | sed 's;^// ;;' | sh > _$i && gofmt < _$i > $i
rm _$i
done
exit 0
;;
-n)
run="cat"
shift
esac
case "$#" in
0)
;;
*)
echo 'usage: mkall.sh [-n]' 1>&2
exit 2
esac
case "$GOOSARCH" in
_* | *_ | _)
echo 'undefined $GOOS_$GOARCH:' "$GOOSARCH" 1>&2
exit 1
;;
plan9_386)
mkerrors=
mksyscall="go run mksyscall.go -l32 -plan9 -tags plan9,386"
mksysnum="./mksysnum_plan9.sh /n/sources/plan9/sys/src/libc/9syscall/sys.h"
mktypes="XXX"
;;
plan9_amd64)
mkerrors=
mksyscall="go run mksyscall.go -l32 -plan9 -tags plan9,amd64"
mksysnum="./mksysnum_plan9.sh /n/sources/plan9/sys/src/libc/9syscall/sys.h"
mktypes="XXX"
;;
plan9_arm)
mkerrors=
mksyscall="go run mksyscall.go -l32 -plan9 -tags plan9,arm"
mksysnum="./mksysnum_plan9.sh /n/sources/plan9/sys/src/libc/9syscall/sys.h"
mktypes="XXX"
;;
*)
echo 'unrecognized $GOOS_$GOARCH: ' "$GOOSARCH" 1>&2
exit 1
;;
esac
(
if [ -n "$mkerrors" ]; then echo "$mkerrors |gofmt >$zerrors"; fi
case "$GOOS" in
plan9)
syscall_goos="syscall_$GOOS.go"
if [ -n "$mksyscall" ]; then echo "$mksyscall $syscall_goos |gofmt >zsyscall_$GOOSARCH.go"; fi
;;
esac
if [ -n "$mksysctl" ]; then echo "$mksysctl |gofmt >$zsysctl"; fi
if [ -n "$mksysnum" ]; then echo "$mksysnum |gofmt >zsysnum_$GOOSARCH.go"; fi
if [ -n "$mktypes" ]; then echo "$mktypes types_$GOOS.go |gofmt >ztypes_$GOOSARCH.go"; fi
) | $run

246
vendor/golang.org/x/sys/plan9/mkerrors.sh generated vendored Normal file
View File

@@ -0,0 +1,246 @@
#!/usr/bin/env bash
# Copyright 2009 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.
# Generate Go code listing errors and other #defined constant
# values (ENAMETOOLONG etc.), by asking the preprocessor
# about the definitions.
unset LANG
export LC_ALL=C
export LC_CTYPE=C
CC=${CC:-gcc}
uname=$(uname)
includes='
#include <sys/types.h>
#include <sys/file.h>
#include <fcntl.h>
#include <dirent.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip6.h>
#include <netinet/tcp.h>
#include <errno.h>
#include <sys/signal.h>
#include <signal.h>
#include <sys/resource.h>
'
ccflags="$@"
# Write go tool cgo -godefs input.
(
echo package plan9
echo
echo '/*'
indirect="includes_$(uname)"
echo "${!indirect} $includes"
echo '*/'
echo 'import "C"'
echo
echo 'const ('
# The gcc command line prints all the #defines
# it encounters while processing the input
echo "${!indirect} $includes" | $CC -x c - -E -dM $ccflags |
awk '
$1 != "#define" || $2 ~ /\(/ || $3 == "" {next}
$2 ~ /^E([ABCD]X|[BIS]P|[SD]I|S|FL)$/ {next} # 386 registers
$2 ~ /^(SIGEV_|SIGSTKSZ|SIGRT(MIN|MAX))/ {next}
$2 ~ /^(SCM_SRCRT)$/ {next}
$2 ~ /^(MAP_FAILED)$/ {next}
$2 !~ /^ETH_/ &&
$2 !~ /^EPROC_/ &&
$2 !~ /^EQUIV_/ &&
$2 !~ /^EXPR_/ &&
$2 ~ /^E[A-Z0-9_]+$/ ||
$2 ~ /^B[0-9_]+$/ ||
$2 ~ /^V[A-Z0-9]+$/ ||
$2 ~ /^CS[A-Z0-9]/ ||
$2 ~ /^I(SIG|CANON|CRNL|EXTEN|MAXBEL|STRIP|UTF8)$/ ||
$2 ~ /^IGN/ ||
$2 ~ /^IX(ON|ANY|OFF)$/ ||
$2 ~ /^IN(LCR|PCK)$/ ||
$2 ~ /(^FLU?SH)|(FLU?SH$)/ ||
$2 ~ /^C(LOCAL|READ)$/ ||
$2 == "BRKINT" ||
$2 == "HUPCL" ||
$2 == "PENDIN" ||
$2 == "TOSTOP" ||
$2 ~ /^PAR/ ||
$2 ~ /^SIG[^_]/ ||
$2 ~ /^O[CNPFP][A-Z]+[^_][A-Z]+$/ ||
$2 ~ /^IN_/ ||
$2 ~ /^LOCK_(SH|EX|NB|UN)$/ ||
$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|ICMP6|TCP|EVFILT|NOTE|EV|SHUT|PROT|MAP|PACKET|MSG|SCM|MCL|DT|MADV|PR)_/ ||
$2 == "ICMPV6_FILTER" ||
$2 == "SOMAXCONN" ||
$2 == "NAME_MAX" ||
$2 == "IFNAMSIZ" ||
$2 ~ /^CTL_(MAXNAME|NET|QUERY)$/ ||
$2 ~ /^SYSCTL_VERS/ ||
$2 ~ /^(MS|MNT)_/ ||
$2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ ||
$2 ~ /^(O|F|FD|NAME|S|PTRACE|PT)_/ ||
$2 ~ /^LINUX_REBOOT_CMD_/ ||
$2 ~ /^LINUX_REBOOT_MAGIC[12]$/ ||
$2 !~ "NLA_TYPE_MASK" &&
$2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P)_/ ||
$2 ~ /^SIOC/ ||
$2 ~ /^TIOC/ ||
$2 !~ "RTF_BITS" &&
$2 ~ /^(IFF|IFT|NET_RT|RTM|RTF|RTV|RTA|RTAX)_/ ||
$2 ~ /^BIOC/ ||
$2 ~ /^RUSAGE_(SELF|CHILDREN|THREAD)/ ||
$2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|NOFILE|STACK)|RLIM_INFINITY/ ||
$2 ~ /^PRIO_(PROCESS|PGRP|USER)/ ||
$2 ~ /^CLONE_[A-Z_]+/ ||
$2 !~ /^(BPF_TIMEVAL)$/ &&
$2 ~ /^(BPF|DLT)_/ ||
$2 !~ "WMESGLEN" &&
$2 ~ /^W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", $2, $2)}
$2 ~ /^__WCOREFLAG$/ {next}
$2 ~ /^__W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", substr($2,3), $2)}
{next}
' | sort
echo ')'
) >_const.go
# Pull out the error names for later.
errors=$(
echo '#include <errno.h>' | $CC -x c - -E -dM $ccflags |
awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print $2 }' |
sort
)
# Pull out the signal names for later.
signals=$(
echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags |
awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print $2 }' |
egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT)' |
sort
)
# Again, writing regexps to a file.
echo '#include <errno.h>' | $CC -x c - -E -dM $ccflags |
awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print "^\t" $2 "[ \t]*=" }' |
sort >_error.grep
echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags |
awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print "^\t" $2 "[ \t]*=" }' |
egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT)' |
sort >_signal.grep
echo '// mkerrors.sh' "$@"
echo '// Code generated by the command above; DO NOT EDIT.'
echo
go tool cgo -godefs -- "$@" _const.go >_error.out
cat _error.out | grep -vf _error.grep | grep -vf _signal.grep
echo
echo '// Errors'
echo 'const ('
cat _error.out | grep -f _error.grep | sed 's/=\(.*\)/= Errno(\1)/'
echo ')'
echo
echo '// Signals'
echo 'const ('
cat _error.out | grep -f _signal.grep | sed 's/=\(.*\)/= Signal(\1)/'
echo ')'
# Run C program to print error and syscall strings.
(
echo -E "
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include <string.h>
#include <signal.h>
#define nelem(x) (sizeof(x)/sizeof((x)[0]))
enum { A = 'A', Z = 'Z', a = 'a', z = 'z' }; // avoid need for single quotes below
int errors[] = {
"
for i in $errors
do
echo -E ' '$i,
done
echo -E "
};
int signals[] = {
"
for i in $signals
do
echo -E ' '$i,
done
# Use -E because on some systems bash builtin interprets \n itself.
echo -E '
};
static int
intcmp(const void *a, const void *b)
{
return *(int*)a - *(int*)b;
}
int
main(void)
{
int i, j, e;
char buf[1024], *p;
printf("\n\n// Error table\n");
printf("var errors = [...]string {\n");
qsort(errors, nelem(errors), sizeof errors[0], intcmp);
for(i=0; i<nelem(errors); i++) {
e = errors[i];
if(i > 0 && errors[i-1] == e)
continue;
strcpy(buf, strerror(e));
// lowercase first letter: Bad -> bad, but STREAM -> STREAM.
if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z)
buf[0] += a - A;
printf("\t%d: \"%s\",\n", e, buf);
}
printf("}\n\n");
printf("\n\n// Signal table\n");
printf("var signals = [...]string {\n");
qsort(signals, nelem(signals), sizeof signals[0], intcmp);
for(i=0; i<nelem(signals); i++) {
e = signals[i];
if(i > 0 && signals[i-1] == e)
continue;
strcpy(buf, strsignal(e));
// lowercase first letter: Bad -> bad, but STREAM -> STREAM.
if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z)
buf[0] += a - A;
// cut trailing : number.
p = strrchr(buf, ":"[0]);
if(p)
*p = '\0';
printf("\t%d: \"%s\",\n", e, buf);
}
printf("}\n\n");
return 0;
}
'
) >_errors.c
$CC $ccflags -o _errors _errors.c && $GORUN ./_errors && rm -f _errors.c _errors _const.go _error.grep _signal.grep _error.out

23
vendor/golang.org/x/sys/plan9/mksysnum_plan9.sh generated vendored Normal file
View File

@@ -0,0 +1,23 @@
#!/bin/sh
# Copyright 2009 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.
COMMAND="mksysnum_plan9.sh $@"
cat <<EOF
// $COMMAND
// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
package plan9
const(
EOF
SP='[ ]' # space or tab
sed "s/^#define${SP}\\([A-Z0-9_][A-Z0-9_]*\\)${SP}${SP}*\\([0-9][0-9]*\\)/SYS_\\1=\\2/g" \
< $1 | grep -v SYS__
cat <<EOF
)
EOF

21
vendor/golang.org/x/sys/plan9/pwd_go15_plan9.go generated vendored Normal file
View File

@@ -0,0 +1,21 @@
// Copyright 2015 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.
// +build go1.5
package plan9
import "syscall"
func fixwd() {
syscall.Fixwd()
}
func Getwd() (wd string, err error) {
return syscall.Getwd()
}
func Chdir(path string) error {
return syscall.Chdir(path)
}

23
vendor/golang.org/x/sys/plan9/pwd_plan9.go generated vendored Normal file
View File

@@ -0,0 +1,23 @@
// Copyright 2015 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.
// +build !go1.5
package plan9
func fixwd() {
}
func Getwd() (wd string, err error) {
fd, err := open(".", O_RDONLY)
if err != nil {
return "", err
}
defer Close(fd)
return Fd2path(fd)
}
func Chdir(path string) error {
return chdir(path)
}

30
vendor/golang.org/x/sys/plan9/race.go generated vendored Normal file
View File

@@ -0,0 +1,30 @@
// 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.
// +build plan9,race
package plan9
import (
"runtime"
"unsafe"
)
const raceenabled = true
func raceAcquire(addr unsafe.Pointer) {
runtime.RaceAcquire(addr)
}
func raceReleaseMerge(addr unsafe.Pointer) {
runtime.RaceReleaseMerge(addr)
}
func raceReadRange(addr unsafe.Pointer, len int) {
runtime.RaceReadRange(addr, len)
}
func raceWriteRange(addr unsafe.Pointer, len int) {
runtime.RaceWriteRange(addr, len)
}

25
vendor/golang.org/x/sys/plan9/race0.go generated vendored Normal file
View File

@@ -0,0 +1,25 @@
// 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.
// +build plan9,!race
package plan9
import (
"unsafe"
)
const raceenabled = false
func raceAcquire(addr unsafe.Pointer) {
}
func raceReleaseMerge(addr unsafe.Pointer) {
}
func raceReadRange(addr unsafe.Pointer, len int) {
}
func raceWriteRange(addr unsafe.Pointer, len int) {
}

22
vendor/golang.org/x/sys/plan9/str.go generated vendored Normal file
View File

@@ -0,0 +1,22 @@
// Copyright 2009 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.
// +build plan9
package plan9
func itoa(val int) string { // do it here rather than with fmt to avoid dependency
if val < 0 {
return "-" + itoa(-val)
}
var buf [32]byte // big enough for int64
i := len(buf) - 1
for val >= 10 {
buf[i] = byte(val%10 + '0')
i--
val /= 10
}
buf[i] = byte(val + '0')
return string(buf[i:])
}

77
vendor/golang.org/x/sys/plan9/syscall.go generated vendored Normal file
View File

@@ -0,0 +1,77 @@
// Copyright 2009 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.
// +build plan9
// Package plan9 contains an interface to the low-level operating system
// primitives. OS details vary depending on the underlying system, and
// by default, godoc will display the OS-specific documentation for the current
// system. If you want godoc to display documentation for another
// system, set $GOOS and $GOARCH to the desired system. For example, if
// you want to view documentation for freebsd/arm on linux/amd64, set $GOOS
// to freebsd and $GOARCH to arm.
//
// The primary use of this package is inside other packages that provide a more
// portable interface to the system, such as "os", "time" and "net". Use
// those packages rather than this one if you can.
//
// For details of the functions and data types in this package consult
// the manuals for the appropriate operating system.
//
// These calls return err == nil to indicate success; otherwise
// err represents an operating system error describing the failure and
// holds a value of type syscall.ErrorString.
package plan9 // import "golang.org/x/sys/plan9"
import "unsafe"
// ByteSliceFromString returns a NUL-terminated slice of bytes
// containing the text of s. If s contains a NUL byte at any
// location, it returns (nil, EINVAL).
func ByteSliceFromString(s string) ([]byte, error) {
for i := 0; i < len(s); i++ {
if s[i] == 0 {
return nil, EINVAL
}
}
a := make([]byte, len(s)+1)
copy(a, s)
return a, nil
}
// BytePtrFromString returns a pointer to a NUL-terminated array of
// bytes containing the text of s. If s contains a NUL byte at any
// location, it returns (nil, EINVAL).
func BytePtrFromString(s string) (*byte, error) {
a, err := ByteSliceFromString(s)
if err != nil {
return nil, err
}
return &a[0], nil
}
// Single-word zero for use when we need a valid pointer to 0 bytes.
// See mksyscall.pl.
var _zero uintptr
func (ts *Timespec) Unix() (sec int64, nsec int64) {
return int64(ts.Sec), int64(ts.Nsec)
}
func (tv *Timeval) Unix() (sec int64, nsec int64) {
return int64(tv.Sec), int64(tv.Usec) * 1000
}
func (ts *Timespec) Nano() int64 {
return int64(ts.Sec)*1e9 + int64(ts.Nsec)
}
func (tv *Timeval) Nano() int64 {
return int64(tv.Sec)*1e9 + int64(tv.Usec)*1000
}
// use is a no-op, but the compiler cannot see that it is.
// Calling use(p) ensures that p is kept live until that point.
//go:noescape
func use(p unsafe.Pointer)

349
vendor/golang.org/x/sys/plan9/syscall_plan9.go generated vendored Normal file
View File

@@ -0,0 +1,349 @@
// 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.
// Plan 9 system calls.
// This file is compiled as ordinary Go code,
// but it is also input to mksyscall,
// which parses the //sys lines and generates system call stubs.
// Note that sometimes we use a lowercase //sys name and
// wrap it in our own nicer implementation.
package plan9
import (
"bytes"
"syscall"
"unsafe"
)
// A Note is a string describing a process note.
// It implements the os.Signal interface.
type Note string
func (n Note) Signal() {}
func (n Note) String() string {
return string(n)
}
var (
Stdin = 0
Stdout = 1
Stderr = 2
)
// For testing: clients can set this flag to force
// creation of IPv6 sockets to return EAFNOSUPPORT.
var SocketDisableIPv6 bool
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.ErrorString)
func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.ErrorString)
func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
func atoi(b []byte) (n uint) {
n = 0
for i := 0; i < len(b); i++ {
n = n*10 + uint(b[i]-'0')
}
return
}
func cstring(s []byte) string {
i := bytes.IndexByte(s, 0)
if i == -1 {
i = len(s)
}
return string(s[:i])
}
func errstr() string {
var buf [ERRMAX]byte
RawSyscall(SYS_ERRSTR, uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf)), 0)
buf[len(buf)-1] = 0
return cstring(buf[:])
}
// Implemented in assembly to import from runtime.
func exit(code int)
func Exit(code int) { exit(code) }
func readnum(path string) (uint, error) {
var b [12]byte
fd, e := Open(path, O_RDONLY)
if e != nil {
return 0, e
}
defer Close(fd)
n, e := Pread(fd, b[:], 0)
if e != nil {
return 0, e
}
m := 0
for ; m < n && b[m] == ' '; m++ {
}
return atoi(b[m : n-1]), nil
}
func Getpid() (pid int) {
n, _ := readnum("#c/pid")
return int(n)
}
func Getppid() (ppid int) {
n, _ := readnum("#c/ppid")
return int(n)
}
func Read(fd int, p []byte) (n int, err error) {
return Pread(fd, p, -1)
}
func Write(fd int, p []byte) (n int, err error) {
return Pwrite(fd, p, -1)
}
var ioSync int64
//sys fd2path(fd int, buf []byte) (err error)
func Fd2path(fd int) (path string, err error) {
var buf [512]byte
e := fd2path(fd, buf[:])
if e != nil {
return "", e
}
return cstring(buf[:]), nil
}
//sys pipe(p *[2]int32) (err error)
func Pipe(p []int) (err error) {
if len(p) != 2 {
return syscall.ErrorString("bad arg in system call")
}
var pp [2]int32
err = pipe(&pp)
p[0] = int(pp[0])
p[1] = int(pp[1])
return
}
// Underlying system call writes to newoffset via pointer.
// Implemented in assembly to avoid allocation.
func seek(placeholder uintptr, fd int, offset int64, whence int) (newoffset int64, err string)
func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
newoffset, e := seek(0, fd, offset, whence)
if newoffset == -1 {
err = syscall.ErrorString(e)
}
return
}
func Mkdir(path string, mode uint32) (err error) {
fd, err := Create(path, O_RDONLY, DMDIR|mode)
if fd != -1 {
Close(fd)
}
return
}
type Waitmsg struct {
Pid int
Time [3]uint32
Msg string
}
func (w Waitmsg) Exited() bool { return true }
func (w Waitmsg) Signaled() bool { return false }
func (w Waitmsg) ExitStatus() int {
if len(w.Msg) == 0 {
// a normal exit returns no message
return 0
}
return 1
}
//sys await(s []byte) (n int, err error)
func Await(w *Waitmsg) (err error) {
var buf [512]byte
var f [5][]byte
n, err := await(buf[:])
if err != nil || w == nil {
return
}
nf := 0
p := 0
for i := 0; i < n && nf < len(f)-1; i++ {
if buf[i] == ' ' {
f[nf] = buf[p:i]
p = i + 1
nf++
}
}
f[nf] = buf[p:]
nf++
if nf != len(f) {
return syscall.ErrorString("invalid wait message")
}
w.Pid = int(atoi(f[0]))
w.Time[0] = uint32(atoi(f[1]))
w.Time[1] = uint32(atoi(f[2]))
w.Time[2] = uint32(atoi(f[3]))
w.Msg = cstring(f[4])
if w.Msg == "''" {
// await() returns '' for no error
w.Msg = ""
}
return
}
func Unmount(name, old string) (err error) {
fixwd()
oldp, err := BytePtrFromString(old)
if err != nil {
return err
}
oldptr := uintptr(unsafe.Pointer(oldp))
var r0 uintptr
var e syscall.ErrorString
// bind(2) man page: If name is zero, everything bound or mounted upon old is unbound or unmounted.
if name == "" {
r0, _, e = Syscall(SYS_UNMOUNT, _zero, oldptr, 0)
} else {
namep, err := BytePtrFromString(name)
if err != nil {
return err
}
r0, _, e = Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(namep)), oldptr, 0)
}
if int32(r0) == -1 {
err = e
}
return
}
func Fchdir(fd int) (err error) {
path, err := Fd2path(fd)
if err != nil {
return
}
return Chdir(path)
}
type Timespec struct {
Sec int32
Nsec int32
}
type Timeval struct {
Sec int32
Usec int32
}
func NsecToTimeval(nsec int64) (tv Timeval) {
nsec += 999 // round up to microsecond
tv.Usec = int32(nsec % 1e9 / 1e3)
tv.Sec = int32(nsec / 1e9)
return
}
func nsec() int64 {
var scratch int64
r0, _, _ := Syscall(SYS_NSEC, uintptr(unsafe.Pointer(&scratch)), 0, 0)
// TODO(aram): remove hack after I fix _nsec in the pc64 kernel.
if r0 == 0 {
return scratch
}
return int64(r0)
}
func Gettimeofday(tv *Timeval) error {
nsec := nsec()
*tv = NsecToTimeval(nsec)
return nil
}
func Getpagesize() int { return 0x1000 }
func Getegid() (egid int) { return -1 }
func Geteuid() (euid int) { return -1 }
func Getgid() (gid int) { return -1 }
func Getuid() (uid int) { return -1 }
func Getgroups() (gids []int, err error) {
return make([]int, 0), nil
}
//sys open(path string, mode int) (fd int, err error)
func Open(path string, mode int) (fd int, err error) {
fixwd()
return open(path, mode)
}
//sys create(path string, mode int, perm uint32) (fd int, err error)
func Create(path string, mode int, perm uint32) (fd int, err error) {
fixwd()
return create(path, mode, perm)
}
//sys remove(path string) (err error)
func Remove(path string) error {
fixwd()
return remove(path)
}
//sys stat(path string, edir []byte) (n int, err error)
func Stat(path string, edir []byte) (n int, err error) {
fixwd()
return stat(path, edir)
}
//sys bind(name string, old string, flag int) (err error)
func Bind(name string, old string, flag int) (err error) {
fixwd()
return bind(name, old, flag)
}
//sys mount(fd int, afd int, old string, flag int, aname string) (err error)
func Mount(fd int, afd int, old string, flag int, aname string) (err error) {
fixwd()
return mount(fd, afd, old, flag, aname)
}
//sys wstat(path string, edir []byte) (err error)
func Wstat(path string, edir []byte) (err error) {
fixwd()
return wstat(path, edir)
}
//sys chdir(path string) (err error)
//sys Dup(oldfd int, newfd int) (fd int, err error)
//sys Pread(fd int, p []byte, offset int64) (n int, err error)
//sys Pwrite(fd int, p []byte, offset int64) (n int, err error)
//sys Close(fd int) (err error)
//sys Fstat(fd int, edir []byte) (n int, err error)
//sys Fwstat(fd int, edir []byte) (err error)

284
vendor/golang.org/x/sys/plan9/zsyscall_plan9_386.go generated vendored Normal file
View File

@@ -0,0 +1,284 @@
// go run mksyscall.go -l32 -plan9 -tags plan9,386 syscall_plan9.go
// Code generated by the command above; see README.md. DO NOT EDIT.
// +build plan9,386
package plan9
import "unsafe"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func fd2path(fd int, buf []byte) (err error) {
var _p0 unsafe.Pointer
if len(buf) > 0 {
_p0 = unsafe.Pointer(&buf[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_FD2PATH, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func pipe(p *[2]int32) (err error) {
r0, _, e1 := Syscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func await(s []byte) (n int, err error) {
var _p0 unsafe.Pointer
if len(s) > 0 {
_p0 = unsafe.Pointer(&s[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_AWAIT, uintptr(_p0), uintptr(len(s)), 0)
n = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func open(path string, mode int) (fd int, err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
fd = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func create(path string, mode int, perm uint32) (fd int, err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
r0, _, e1 := Syscall(SYS_CREATE, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
fd = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func remove(path string) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
r0, _, e1 := Syscall(SYS_REMOVE, uintptr(unsafe.Pointer(_p0)), 0, 0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func stat(path string, edir []byte) (n int, err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
var _p1 unsafe.Pointer
if len(edir) > 0 {
_p1 = unsafe.Pointer(&edir[0])
} else {
_p1 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir)))
n = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func bind(name string, old string, flag int) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(name)
if err != nil {
return
}
var _p1 *byte
_p1, err = BytePtrFromString(old)
if err != nil {
return
}
r0, _, e1 := Syscall(SYS_BIND, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flag))
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func mount(fd int, afd int, old string, flag int, aname string) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(old)
if err != nil {
return
}
var _p1 *byte
_p1, err = BytePtrFromString(aname)
if err != nil {
return
}
r0, _, e1 := Syscall6(SYS_MOUNT, uintptr(fd), uintptr(afd), uintptr(unsafe.Pointer(_p0)), uintptr(flag), uintptr(unsafe.Pointer(_p1)), 0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func wstat(path string, edir []byte) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
var _p1 unsafe.Pointer
if len(edir) > 0 {
_p1 = unsafe.Pointer(&edir[0])
} else {
_p1 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_WSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir)))
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func chdir(path string) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
r0, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Dup(oldfd int, newfd int) (fd int, err error) {
r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), uintptr(newfd), 0)
fd = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
n = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
n = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Close(fd int) (err error) {
r0, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Fstat(fd int, edir []byte) (n int, err error) {
var _p0 unsafe.Pointer
if len(edir) > 0 {
_p0 = unsafe.Pointer(&edir[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
n = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Fwstat(fd int, edir []byte) (err error) {
var _p0 unsafe.Pointer
if len(edir) > 0 {
_p0 = unsafe.Pointer(&edir[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_FWSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
if int32(r0) == -1 {
err = e1
}
return
}

284
vendor/golang.org/x/sys/plan9/zsyscall_plan9_amd64.go generated vendored Normal file
View File

@@ -0,0 +1,284 @@
// go run mksyscall.go -l32 -plan9 -tags plan9,amd64 syscall_plan9.go
// Code generated by the command above; see README.md. DO NOT EDIT.
// +build plan9,amd64
package plan9
import "unsafe"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func fd2path(fd int, buf []byte) (err error) {
var _p0 unsafe.Pointer
if len(buf) > 0 {
_p0 = unsafe.Pointer(&buf[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_FD2PATH, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func pipe(p *[2]int32) (err error) {
r0, _, e1 := Syscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func await(s []byte) (n int, err error) {
var _p0 unsafe.Pointer
if len(s) > 0 {
_p0 = unsafe.Pointer(&s[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_AWAIT, uintptr(_p0), uintptr(len(s)), 0)
n = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func open(path string, mode int) (fd int, err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
fd = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func create(path string, mode int, perm uint32) (fd int, err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
r0, _, e1 := Syscall(SYS_CREATE, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
fd = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func remove(path string) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
r0, _, e1 := Syscall(SYS_REMOVE, uintptr(unsafe.Pointer(_p0)), 0, 0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func stat(path string, edir []byte) (n int, err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
var _p1 unsafe.Pointer
if len(edir) > 0 {
_p1 = unsafe.Pointer(&edir[0])
} else {
_p1 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir)))
n = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func bind(name string, old string, flag int) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(name)
if err != nil {
return
}
var _p1 *byte
_p1, err = BytePtrFromString(old)
if err != nil {
return
}
r0, _, e1 := Syscall(SYS_BIND, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flag))
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func mount(fd int, afd int, old string, flag int, aname string) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(old)
if err != nil {
return
}
var _p1 *byte
_p1, err = BytePtrFromString(aname)
if err != nil {
return
}
r0, _, e1 := Syscall6(SYS_MOUNT, uintptr(fd), uintptr(afd), uintptr(unsafe.Pointer(_p0)), uintptr(flag), uintptr(unsafe.Pointer(_p1)), 0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func wstat(path string, edir []byte) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
var _p1 unsafe.Pointer
if len(edir) > 0 {
_p1 = unsafe.Pointer(&edir[0])
} else {
_p1 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_WSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir)))
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func chdir(path string) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
r0, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Dup(oldfd int, newfd int) (fd int, err error) {
r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), uintptr(newfd), 0)
fd = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
n = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
n = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Close(fd int) (err error) {
r0, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Fstat(fd int, edir []byte) (n int, err error) {
var _p0 unsafe.Pointer
if len(edir) > 0 {
_p0 = unsafe.Pointer(&edir[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
n = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Fwstat(fd int, edir []byte) (err error) {
var _p0 unsafe.Pointer
if len(edir) > 0 {
_p0 = unsafe.Pointer(&edir[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_FWSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
if int32(r0) == -1 {
err = e1
}
return
}

284
vendor/golang.org/x/sys/plan9/zsyscall_plan9_arm.go generated vendored Normal file
View File

@@ -0,0 +1,284 @@
// go run mksyscall.go -l32 -plan9 -tags plan9,arm syscall_plan9.go
// Code generated by the command above; see README.md. DO NOT EDIT.
// +build plan9,arm
package plan9
import "unsafe"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func fd2path(fd int, buf []byte) (err error) {
var _p0 unsafe.Pointer
if len(buf) > 0 {
_p0 = unsafe.Pointer(&buf[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_FD2PATH, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func pipe(p *[2]int32) (err error) {
r0, _, e1 := Syscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func await(s []byte) (n int, err error) {
var _p0 unsafe.Pointer
if len(s) > 0 {
_p0 = unsafe.Pointer(&s[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_AWAIT, uintptr(_p0), uintptr(len(s)), 0)
n = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func open(path string, mode int) (fd int, err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
fd = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func create(path string, mode int, perm uint32) (fd int, err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
r0, _, e1 := Syscall(SYS_CREATE, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm))
fd = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func remove(path string) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
r0, _, e1 := Syscall(SYS_REMOVE, uintptr(unsafe.Pointer(_p0)), 0, 0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func stat(path string, edir []byte) (n int, err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
var _p1 unsafe.Pointer
if len(edir) > 0 {
_p1 = unsafe.Pointer(&edir[0])
} else {
_p1 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir)))
n = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func bind(name string, old string, flag int) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(name)
if err != nil {
return
}
var _p1 *byte
_p1, err = BytePtrFromString(old)
if err != nil {
return
}
r0, _, e1 := Syscall(SYS_BIND, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flag))
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func mount(fd int, afd int, old string, flag int, aname string) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(old)
if err != nil {
return
}
var _p1 *byte
_p1, err = BytePtrFromString(aname)
if err != nil {
return
}
r0, _, e1 := Syscall6(SYS_MOUNT, uintptr(fd), uintptr(afd), uintptr(unsafe.Pointer(_p0)), uintptr(flag), uintptr(unsafe.Pointer(_p1)), 0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func wstat(path string, edir []byte) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
var _p1 unsafe.Pointer
if len(edir) > 0 {
_p1 = unsafe.Pointer(&edir[0])
} else {
_p1 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_WSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir)))
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func chdir(path string) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
r0, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Dup(oldfd int, newfd int) (fd int, err error) {
r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), uintptr(newfd), 0)
fd = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
n = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
n = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Close(fd int) (err error) {
r0, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Fstat(fd int, edir []byte) (n int, err error) {
var _p0 unsafe.Pointer
if len(edir) > 0 {
_p0 = unsafe.Pointer(&edir[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
n = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Fwstat(fd int, edir []byte) (err error) {
var _p0 unsafe.Pointer
if len(edir) > 0 {
_p0 = unsafe.Pointer(&edir[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall(SYS_FWSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
if int32(r0) == -1 {
err = e1
}
return
}

49
vendor/golang.org/x/sys/plan9/zsysnum_plan9.go generated vendored Normal file
View File

@@ -0,0 +1,49 @@
// mksysnum_plan9.sh /opt/plan9/sys/src/libc/9syscall/sys.h
// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
package plan9
const (
SYS_SYSR1 = 0
SYS_BIND = 2
SYS_CHDIR = 3
SYS_CLOSE = 4
SYS_DUP = 5
SYS_ALARM = 6
SYS_EXEC = 7
SYS_EXITS = 8
SYS_FAUTH = 10
SYS_SEGBRK = 12
SYS_OPEN = 14
SYS_OSEEK = 16
SYS_SLEEP = 17
SYS_RFORK = 19
SYS_PIPE = 21
SYS_CREATE = 22
SYS_FD2PATH = 23
SYS_BRK_ = 24
SYS_REMOVE = 25
SYS_NOTIFY = 28
SYS_NOTED = 29
SYS_SEGATTACH = 30
SYS_SEGDETACH = 31
SYS_SEGFREE = 32
SYS_SEGFLUSH = 33
SYS_RENDEZVOUS = 34
SYS_UNMOUNT = 35
SYS_SEMACQUIRE = 37
SYS_SEMRELEASE = 38
SYS_SEEK = 39
SYS_FVERSION = 40
SYS_ERRSTR = 41
SYS_STAT = 42
SYS_FSTAT = 43
SYS_WSTAT = 44
SYS_FWSTAT = 45
SYS_MOUNT = 46
SYS_AWAIT = 47
SYS_PREAD = 50
SYS_PWRITE = 51
SYS_TSEMACQUIRE = 52
SYS_NSEC = 53
)

View File

@@ -14,7 +14,7 @@ migrating the build system to use containers so the builds are reproducible.
This is being done on an OS-by-OS basis. Please update this documentation as
components of the build system change.
### Old Build System (currently for `GOOS != "Linux" || GOARCH == "sparc64"`)
### Old Build System (currently for `GOOS != "linux"`)
The old build system generates the Go files based on the C header files
present on your system. This means that files
@@ -32,9 +32,9 @@ To build the files for your current OS and architecture, make sure GOOS and
GOARCH are set correctly and run `mkall.sh`. This will generate the files for
your specific system. Running `mkall.sh -n` shows the commands that will be run.
Requirements: bash, perl, go
Requirements: bash, go
### New Build System (currently for `GOOS == "Linux" && GOARCH != "sparc64"`)
### New Build System (currently for `GOOS == "linux"`)
The new build system uses a Docker container to generate the go files directly
from source checkouts of the kernel and various system libraries. This means
@@ -52,14 +52,14 @@ system and have your GOOS and GOARCH set accordingly. Running `mkall.sh` will
then generate all of the files for all of the GOOS/GOARCH pairs in the new build
system. Running `mkall.sh -n` shows the commands that will be run.
Requirements: bash, perl, go, docker
Requirements: bash, go, docker
## Component files
This section describes the various files used in the code generation process.
It also contains instructions on how to modify these files to add a new
architecture/OS or to add additional syscalls, types, or constants. Note that
if you are using the new build system, the scripts cannot be called normally.
if you are using the new build system, the scripts/programs cannot be called normally.
They must be called from within the docker container.
### asm files
@@ -81,8 +81,8 @@ each GOOS/GOARCH pair.
### mksysnum
Mksysnum is a script located at `${GOOS}/mksysnum.pl` (or `mksysnum_${GOOS}.pl`
for the old system). This script takes in a list of header files containing the
Mksysnum is a Go program located at `${GOOS}/mksysnum.go` (or `mksysnum_${GOOS}.go`
for the old system). This program takes in a list of header files containing the
syscall number declarations and parses them to produce the corresponding list of
Go numeric constants. See `zsysnum_${GOOS}_${GOARCH}.go` for the generated
constants.
@@ -92,14 +92,14 @@ new installation of the target OS (or updating the source checkouts for the
new build system). However, depending on the OS, you make need to update the
parsing in mksysnum.
### mksyscall.pl
### mksyscall.go
The `syscall.go`, `syscall_${GOOS}.go`, `syscall_${GOOS}_${GOARCH}.go` are
hand-written Go files which implement system calls (for unix, the specific OS,
or the specific OS/Architecture pair respectively) that need special handling
and list `//sys` comments giving prototypes for ones that can be generated.
The mksyscall.pl script takes the `//sys` and `//sysnb` comments and converts
The mksyscall.go program takes the `//sys` and `//sysnb` comments and converts
them into syscalls. This requires the name of the prototype in the comment to
match a syscall number in the `zsysnum_${GOOS}_${GOARCH}.go` file. The function
prototype can be exported (capitalized) or not.
@@ -160,7 +160,7 @@ signal numbers, and constants. Generated by `mkerrors.sh` (see above).
### `zsyscall_${GOOS}_${GOARCH}.go`
A file containing all the generated syscalls for a specific GOOS and GOARCH.
Generated by `mksyscall.pl` (see above).
Generated by `mksyscall.go` (see above).
### `zsysnum_${GOOS}_${GOARCH}.go`

View File

@@ -7,6 +7,7 @@
package unix
import (
"math/bits"
"unsafe"
)
@@ -79,46 +80,7 @@ func (s *CPUSet) IsSet(cpu int) bool {
func (s *CPUSet) Count() int {
c := 0
for _, b := range s {
c += onesCount64(uint64(b))
c += bits.OnesCount64(uint64(b))
}
return c
}
// onesCount64 is a copy of Go 1.9's math/bits.OnesCount64.
// Once this package can require Go 1.9, we can delete this
// and update the caller to use bits.OnesCount64.
func onesCount64(x uint64) int {
const m0 = 0x5555555555555555 // 01010101 ...
const m1 = 0x3333333333333333 // 00110011 ...
const m2 = 0x0f0f0f0f0f0f0f0f // 00001111 ...
const m3 = 0x00ff00ff00ff00ff // etc.
const m4 = 0x0000ffff0000ffff
// Implementation: Parallel summing of adjacent bits.
// See "Hacker's Delight", Chap. 5: Counting Bits.
// The following pattern shows the general approach:
//
// x = x>>1&(m0&m) + x&(m0&m)
// x = x>>2&(m1&m) + x&(m1&m)
// x = x>>4&(m2&m) + x&(m2&m)
// x = x>>8&(m3&m) + x&(m3&m)
// x = x>>16&(m4&m) + x&(m4&m)
// x = x>>32&(m5&m) + x&(m5&m)
// return int(x)
//
// Masking (& operations) can be left away when there's no
// danger that a field's sum will carry over into the next
// field: Since the result cannot be > 64, 8 bits is enough
// and we can ignore the masks for the shifts by 8 and up.
// Per "Hacker's Delight", the first line can be simplified
// more, but it saves at best one instruction, so we leave
// it alone for clarity.
const m = 1<<64 - 1
x = x>>1&(m0&m) + x&(m0&m)
x = x>>2&(m1&m) + x&(m1&m)
x = (x>>4 + x) & (m2 & m)
x += x >> 8
x += x >> 16
x += x >> 32
return int(x) & (1<<7 - 1)
}

17
vendor/golang.org/x/sys/unix/asm_aix_ppc64.s generated vendored Normal file
View File

@@ -0,0 +1,17 @@
// Copyright 2018 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.
// +build !gccgo
#include "textflag.h"
//
// System calls for ppc64, AIX are implemented in runtime/syscall_aix.go
//
TEXT ·syscall6(SB),NOSPLIT,$0-88
JMP syscall·syscall6(SB)
TEXT ·rawSyscall6(SB),NOSPLIT,$0-88
JMP syscall·rawSyscall6(SB)

29
vendor/golang.org/x/sys/unix/asm_freebsd_arm64.s generated vendored Normal file
View File

@@ -0,0 +1,29 @@
// Copyright 2018 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.
// +build !gccgo
#include "textflag.h"
//
// System call support for ARM64, FreeBSD
//
// Just jump to package syscall's implementation for all these functions.
// The runtime may know about them.
TEXT ·Syscall(SB),NOSPLIT,$0-56
JMP syscall·Syscall(SB)
TEXT ·Syscall6(SB),NOSPLIT,$0-80
JMP syscall·Syscall6(SB)
TEXT ·Syscall9(SB),NOSPLIT,$0-104
JMP syscall·Syscall9(SB)
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
JMP syscall·RawSyscall(SB)
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
JMP syscall·RawSyscall6(SB)

View File

@@ -15,12 +15,6 @@
// Just jump to package syscall's implementation for all these functions.
// The runtime may know about them.
TEXT ·Syscall(SB),NOSPLIT,$0-56
BR syscall·Syscall(SB)
TEXT ·Syscall6(SB),NOSPLIT,$0-80
BR syscall·Syscall6(SB)
TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
BL runtime·entersyscall(SB)
MOVD a1+8(FP), R3
@@ -36,12 +30,6 @@ TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
BL runtime·exitsyscall(SB)
RET
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
BR syscall·RawSyscall(SB)
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
BR syscall·RawSyscall6(SB)
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
MOVD a1+8(FP), R3
MOVD a2+16(FP), R4

47
vendor/golang.org/x/sys/unix/asm_linux_riscv64.s generated vendored Normal file
View File

@@ -0,0 +1,47 @@
// Copyright 2019 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.
// +build riscv64,!gccgo
#include "textflag.h"
//
// System calls for linux/riscv64.
//
// Where available, just jump to package syscall's implementation of
// these functions.
TEXT ·Syscall(SB),NOSPLIT,$0-56
JMP syscall·Syscall(SB)
TEXT ·Syscall6(SB),NOSPLIT,$0-80
JMP syscall·Syscall6(SB)
TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
CALL runtime·entersyscall(SB)
MOV a1+8(FP), A0
MOV a2+16(FP), A1
MOV a3+24(FP), A2
MOV trap+0(FP), A7 // syscall entry
ECALL
MOV A0, r1+32(FP) // r1
MOV A1, r2+40(FP) // r2
CALL runtime·exitsyscall(SB)
RET
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
JMP syscall·RawSyscall(SB)
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
JMP syscall·RawSyscall6(SB)
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
MOV a1+8(FP), A0
MOV a2+16(FP), A1
MOV a3+24(FP), A2
MOV trap+0(FP), A7 // syscall entry
ECALL
MOV A0, r1+32(FP)
MOV A1, r2+40(FP)
RET

29
vendor/golang.org/x/sys/unix/asm_netbsd_arm64.s generated vendored Normal file
View File

@@ -0,0 +1,29 @@
// Copyright 2019 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.
// +build !gccgo
#include "textflag.h"
//
// System call support for ARM64, NetBSD
//
// Just jump to package syscall's implementation for all these functions.
// The runtime may know about them.
TEXT ·Syscall(SB),NOSPLIT,$0-56
B syscall·Syscall(SB)
TEXT ·Syscall6(SB),NOSPLIT,$0-80
B syscall·Syscall6(SB)
TEXT ·Syscall9(SB),NOSPLIT,$0-104
B syscall·Syscall9(SB)
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
B syscall·RawSyscall(SB)
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
B syscall·RawSyscall6(SB)

29
vendor/golang.org/x/sys/unix/asm_openbsd_arm64.s generated vendored Normal file
View File

@@ -0,0 +1,29 @@
// Copyright 2019 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.
// +build !gccgo
#include "textflag.h"
//
// System call support for arm64, OpenBSD
//
// Just jump to package syscall's implementation for all these functions.
// The runtime may know about them.
TEXT ·Syscall(SB),NOSPLIT,$0-56
JMP syscall·Syscall(SB)
TEXT ·Syscall6(SB),NOSPLIT,$0-80
JMP syscall·Syscall6(SB)
TEXT ·Syscall9(SB),NOSPLIT,$0-104
JMP syscall·Syscall9(SB)
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
JMP syscall·RawSyscall(SB)
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
JMP syscall·RawSyscall6(SB)

Some files were not shown because too many files have changed in this diff Show More