mirror of
https://github.com/strongdm/comply
synced 2025-12-15 10:43:47 +00:00
Compare commits
26 Commits
v1.3.5
...
v1.5.0-dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f5f7c08b73 | ||
|
|
b2276f9e54 | ||
|
|
f1b5bbeff9 | ||
|
|
b7acb1eecf | ||
|
|
da8a574e86 | ||
|
|
7468711b3b | ||
|
|
8baf787ed7 | ||
|
|
4c5c18964b | ||
|
|
c5a1bd804b | ||
|
|
c303b68201 | ||
|
|
87e8266f1b | ||
|
|
e8d6d536a8 | ||
|
|
ef7a4092a7 | ||
|
|
9bcc88eebc | ||
|
|
edd3c7dd44 | ||
|
|
25058359ea | ||
|
|
c4a0b7afff | ||
|
|
ef32942dad | ||
|
|
0c9dbd736b | ||
|
|
b98d179847 | ||
|
|
435ac086c0 | ||
|
|
0ddbb6cf52 | ||
|
|
3ebccc2811 | ||
|
|
b39bec8108 | ||
|
|
c699c64627 | ||
|
|
24ff9dd762 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,3 +2,4 @@ comply
|
||||
output
|
||||
dist
|
||||
.envrc
|
||||
bindata.go
|
||||
21
Dockerfile
Normal file
21
Dockerfile
Normal file
@@ -0,0 +1,21 @@
|
||||
FROM strongdm/pandoc:latest
|
||||
|
||||
# based on implementation by James Gregory <james@jagregory.com>
|
||||
MAINTAINER Comply <comply@strongdm.com>
|
||||
|
||||
RUN apt-get update -y \
|
||||
&& apt-get install -y curl
|
||||
|
||||
ARG COMPLY_VERSION
|
||||
ENV COMPLY_VERSION ${COMPLY_VERSION:-1.4.0}
|
||||
|
||||
EXPOSE 4000/tcp
|
||||
|
||||
# install comply binary
|
||||
RUN curl -J -L -o /tmp/comply.tgz https://github.com/strongdm/comply/releases/download/v${COMPLY_VERSION}/comply-v${COMPLY_VERSION}-linux-amd64.tgz \
|
||||
&& tar -xzf /tmp/comply.tgz \
|
||||
&& mv ./comply-v${COMPLY_VERSION}-linux-amd64 /usr/local/bin/comply
|
||||
|
||||
WORKDIR /source
|
||||
|
||||
ENTRYPOINT ["/bin/bash"]
|
||||
289
Gopkg.lock
generated
289
Gopkg.lock
generated
@@ -1,289 +0,0 @@
|
||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/Microsoft/go-winio"
|
||||
packages = ["."]
|
||||
revision = "7da180ee92d8bd8bb8c37fc560e673e6557c392f"
|
||||
version = "v0.4.7"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/andygrunwald/go-jira"
|
||||
packages = ["."]
|
||||
revision = "5cfdb85cc91c6299f75b6504a1d0ec174c21be39"
|
||||
version = "v1.3.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/chzyer/readline"
|
||||
packages = ["."]
|
||||
revision = "f6d7a1f6fbf35bbf9beb80dc63c56a29dcfb759f"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/davecgh/go-spew"
|
||||
packages = ["spew"]
|
||||
revision = "346938d642f2ec3594ed81d874461961cd0faa76"
|
||||
version = "v1.1.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/docker/distribution"
|
||||
packages = [
|
||||
"digest",
|
||||
"reference"
|
||||
]
|
||||
revision = "48294d928ced5dd9b378f7fd7c6f5da3ff3f2c89"
|
||||
version = "v2.6.2"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/docker/docker"
|
||||
packages = [
|
||||
"api/types",
|
||||
"api/types/blkiodev",
|
||||
"api/types/container",
|
||||
"api/types/events",
|
||||
"api/types/filters",
|
||||
"api/types/mount",
|
||||
"api/types/network",
|
||||
"api/types/reference",
|
||||
"api/types/registry",
|
||||
"api/types/strslice",
|
||||
"api/types/swarm",
|
||||
"api/types/time",
|
||||
"api/types/versions",
|
||||
"api/types/volume",
|
||||
"client",
|
||||
"pkg/tlsconfig"
|
||||
]
|
||||
revision = "092cba3727bb9b4a2f0e922cd6c0f93ea270e363"
|
||||
version = "v1.13.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/docker/go-connections"
|
||||
packages = [
|
||||
"nat",
|
||||
"sockets",
|
||||
"tlsconfig"
|
||||
]
|
||||
revision = "3ede32e2033de7505e6500d6c868c2b9ed9f169d"
|
||||
version = "v0.3.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/docker/go-units"
|
||||
packages = ["."]
|
||||
revision = "0dadbb0345b35ec7ef35e228dabb8de89a65bf52"
|
||||
version = "v0.3.2"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/elazarl/go-bindata-assetfs"
|
||||
packages = ["."]
|
||||
revision = "30f82fa23fd844bd5bb1e5f216db87fd77b5eb43"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/fatih/color"
|
||||
packages = ["."]
|
||||
revision = "507f6050b8568533fb3f5504de8e5205fa62a114"
|
||||
version = "v1.6.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/fatih/structs"
|
||||
packages = ["."]
|
||||
revision = "a720dfa8df582c51dee1b36feabb906bde1588bd"
|
||||
version = "v1.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/fsnotify/fsnotify"
|
||||
packages = ["."]
|
||||
revision = "c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9"
|
||||
version = "v1.4.7"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/gohugoio/hugo"
|
||||
packages = ["watcher"]
|
||||
revision = "f414966b942b5aad75565bee6c644782a07f0658"
|
||||
version = "v0.37.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/golang/protobuf"
|
||||
packages = ["proto"]
|
||||
revision = "925541529c1fa6821df4e44ce2723319eb2be768"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/google/go-github"
|
||||
packages = ["github"]
|
||||
revision = "e48060a28fac52d0f1cb758bc8b87c07bac4a87d"
|
||||
version = "v15.0.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/google/go-querystring"
|
||||
packages = ["query"]
|
||||
revision = "53e6ce116135b80d037921a7fdd5138cf32d7a8a"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/gorilla/websocket"
|
||||
packages = ["."]
|
||||
revision = "ea4d1f681babbce9545c9c5f3d5194a789c89f5b"
|
||||
version = "v1.2.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/jcelliott/lumber"
|
||||
packages = ["."]
|
||||
revision = "dd349441af25132d146d7095c6693a15431fc9b1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/juju/ansiterm"
|
||||
packages = [
|
||||
".",
|
||||
"tabwriter"
|
||||
]
|
||||
revision = "720a0952cc2ac777afc295d9861263e2a4cf96a1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/lunixbochs/vtclean"
|
||||
packages = ["."]
|
||||
revision = "d14193dfc626125c831501c1c42340b4248e1f5a"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/manifoldco/promptui"
|
||||
packages = [
|
||||
".",
|
||||
"list",
|
||||
"screenbuf"
|
||||
]
|
||||
revision = "c0c0d3afc6a03bcb5c1df10b70b862a650db9f9b"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/mattn/go-colorable"
|
||||
packages = ["."]
|
||||
revision = "167de6bfdfba052fa6b2d3664c8f5272e23c9072"
|
||||
version = "v0.0.9"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/mattn/go-isatty"
|
||||
packages = ["."]
|
||||
revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39"
|
||||
version = "v0.0.3"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/mattn/go-runewidth"
|
||||
packages = ["."]
|
||||
revision = "9e777a8366cce605130a531d2cd6363d07ad7317"
|
||||
version = "v0.0.2"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/nanobox-io/golang-scribble"
|
||||
packages = ["."]
|
||||
revision = "ced58d671850da57ce8c11315424513b608083d7"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/olekukonko/tablewriter"
|
||||
packages = ["."]
|
||||
revision = "b8a9be070da40449e501c3c4730a889e42d87a9e"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/pkg/errors"
|
||||
packages = ["."]
|
||||
revision = "645ef00459ed84a119197bfb8d8205042c6df63d"
|
||||
version = "v0.8.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/robfig/cron"
|
||||
packages = ["."]
|
||||
revision = "b024fc5ea0e34bc3f83d9941c8d60b0622bfaca4"
|
||||
version = "v1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/skratchdot/open-golang"
|
||||
packages = ["open"]
|
||||
revision = "75fb7ed4208cf72d323d7d02fd1a5964a7a9073c"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/trivago/tgo"
|
||||
packages = [
|
||||
"tcontainer",
|
||||
"treflect"
|
||||
]
|
||||
revision = "e4d1ddd28c17dd89ed26327cf69fded22060671b"
|
||||
version = "v1.0.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/urfave/cli"
|
||||
packages = ["."]
|
||||
revision = "cfb38830724cc34fedffe9a2a29fb54fa9169cd1"
|
||||
version = "v1.20.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/xanzy/go-gitlab"
|
||||
packages = ["."]
|
||||
revision = "79dad8e74fd097eb2e0fd0883f1978213e88107a"
|
||||
version = "v0.10.7"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/yosssi/ace"
|
||||
packages = ["."]
|
||||
revision = "ea038f4770b6746c3f8f84f14fa60d9fe1205b56"
|
||||
version = "v0.0.5"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/net"
|
||||
packages = [
|
||||
"context",
|
||||
"context/ctxhttp",
|
||||
"proxy"
|
||||
]
|
||||
revision = "d0aafc73d5cdc42264b0af071c261abac580695e"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/oauth2"
|
||||
packages = [
|
||||
".",
|
||||
"internal"
|
||||
]
|
||||
revision = "7af32f14d0a25aec7873e0683e8e48dcead159a8"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/sys"
|
||||
packages = [
|
||||
"unix",
|
||||
"windows"
|
||||
]
|
||||
revision = "dd2ff4accc098aceecb86b36eaa7829b2a17b1c9"
|
||||
|
||||
[[projects]]
|
||||
name = "google.golang.org/appengine"
|
||||
packages = [
|
||||
"internal",
|
||||
"internal/base",
|
||||
"internal/datastore",
|
||||
"internal/log",
|
||||
"internal/remote_api",
|
||||
"internal/urlfetch",
|
||||
"urlfetch"
|
||||
]
|
||||
revision = "150dc57a1b433e64154302bdc40b6bb8aefa313a"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
name = "gopkg.in/yaml.v2"
|
||||
packages = ["."]
|
||||
revision = "7f97868eec74b32b0982dd158a51a446d1da7eb5"
|
||||
version = "v2.1.1"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "50dc710fa4b581d4fd6907e0e3337c53c3d530e46c53aa71ef9f8e80d3a54d8b"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
30
Gopkg.toml
30
Gopkg.toml
@@ -1,30 +0,0 @@
|
||||
# Gopkg.toml example
|
||||
#
|
||||
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
|
||||
# for detailed Gopkg.toml documentation.
|
||||
#
|
||||
# required = ["github.com/user/thing/cmd/thing"]
|
||||
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project"
|
||||
# version = "1.0.0"
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project2"
|
||||
# branch = "dev"
|
||||
# source = "github.com/myfork/project2"
|
||||
#
|
||||
# [[override]]
|
||||
# name = "github.com/x/y"
|
||||
# version = "2.4.0"
|
||||
#
|
||||
# [prune]
|
||||
# non-go = false
|
||||
# go-tests = true
|
||||
# unused-packages = true
|
||||
|
||||
|
||||
[prune]
|
||||
go-tests = true
|
||||
unused-packages = true
|
||||
31
Makefile
31
Makefile
@@ -3,10 +3,9 @@ GO_SOURCES := $(shell find . -name '*.go')
|
||||
THEME_SOURCES := $(shell find themes)
|
||||
|
||||
assets: $(THEME_SOURCES)
|
||||
@go get github.com/jteeuwen/go-bindata/...
|
||||
@go get github.com/elazarl/go-bindata-assetfs/...
|
||||
@go install github.com/elazarl/go-bindata-assetfs
|
||||
go-bindata-assetfs -o bindata.go -pkg theme -prefix themes themes/...
|
||||
go install -mod=vendor github.com/containous/go-bindata/go-bindata
|
||||
go install -mod=vendor github.com/elazarl/go-bindata-assetfs/go-bindata-assetfs
|
||||
go-bindata-assetfs -pkg theme -prefix themes themes/...
|
||||
mv bindata.go internal/theme/themes_bindata.go
|
||||
|
||||
comply: assets $(GO_SOURCES)
|
||||
@@ -40,7 +39,7 @@ clean:
|
||||
install: assets $(GO_SOURCES)
|
||||
go install github.com/strongdm/comply
|
||||
|
||||
push-assets: is-clean export-example assets
|
||||
push-assets: is-clean assets
|
||||
git commit -am "automated asset refresh (via Makefile)"
|
||||
git push
|
||||
|
||||
@@ -52,16 +51,6 @@ else
|
||||
@exit 1
|
||||
endif
|
||||
|
||||
export-example:
|
||||
cp example/narratives/* themes/comply-soc2/narratives
|
||||
cp example/procedures/* themes/comply-soc2/procedures
|
||||
cp example/policies/* themes/comply-soc2/policies
|
||||
cp example/standards/* themes/comply-soc2/standards
|
||||
cp example/templates/* themes/comply-soc2/templates
|
||||
cp example/templates/* themes/comply-blank/templates
|
||||
cp example/*.md themes/comply-soc2
|
||||
cp example/*.md themes/comply-blank
|
||||
|
||||
docker:
|
||||
cd build && docker build -t strongdm/pandoc .
|
||||
docker push strongdm/pandoc
|
||||
@@ -113,14 +102,18 @@ release: release-env dist release-deps
|
||||
@echo "version $(VERSION) sha $(SHA)"
|
||||
cd $$COMPLY_TAPDIR && ./update.sh $(VERSION) $(SHA)
|
||||
|
||||
patch-release: release-env push-assets patch release
|
||||
patch-release: release-env patch release
|
||||
$(eval VERSION := $(shell git describe --tags --always --dirty="-dev"))
|
||||
curl -X POST --data-urlencode 'payload={"channel": "#release", "username": "release", "text": "comply $(VERSION) released", "icon_emoji": ":shipit:"}' https://hooks.slack.com/services/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
|
||||
|
||||
minor-release: release-env push-assets minor release
|
||||
minor-release: release-env minor release
|
||||
$(eval VERSION := $(shell git describe --tags --always --dirty="-dev"))
|
||||
curl -X POST --data-urlencode 'payload={"channel": "#release", "username": "release", "text": "comply $(VERSION) released", "icon_emoji": ":shipit:"}' https://hooks.slack.com/services/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
|
||||
|
||||
docker-release:
|
||||
docker build --build-arg COMPLY_VERSION=`cat VERSION` -t strongdm/comply .
|
||||
docker push strongdm/comply
|
||||
|
||||
patch: clean gitsem
|
||||
gitsem -m "increment patch for release (via Makefile)" patch
|
||||
git push
|
||||
@@ -134,7 +127,7 @@ minor: clean gitsem
|
||||
release-deps: gitsem gh-release
|
||||
|
||||
gitsem:
|
||||
go get -u github.com/Clever/gitsem
|
||||
go install github.com/Clever/gitsem
|
||||
|
||||
gh-release:
|
||||
go get -u github.com/aktau/github-release
|
||||
go install github.com/aktau/github-release
|
||||
23
README.md
23
README.md
@@ -77,6 +77,29 @@ COMMANDS:
|
||||
todo list declared vs satisfied compliance controls
|
||||
help, h Shows a list of commands or help for one command
|
||||
```
|
||||
|
||||
## Running in Docker
|
||||
|
||||
Comply is currently only released for Linux and macOS, however from other operating systems it's possible to run using Docker:
|
||||
|
||||
```
|
||||
# first pull the latest published docker image
|
||||
$ docker pull strongdm/comply
|
||||
|
||||
# from an empty directory that will contain your comply project
|
||||
$ docker run --rm -v "$PWD":/source -p 4000:4000 -it strongdm/comply
|
||||
root@ec4544732298:/source# comply init
|
||||
✗ Organization Name:
|
||||
|
||||
# serve content live from an established project
|
||||
$ docker run --rm -v "$PWD":/source -p 4000:4000 -it strongdm/comply
|
||||
root@ae4d499583fc:/source# comply serve
|
||||
Serving content of output/ at http://127.0.0.1:4000 (ctrl-c to quit)
|
||||
```
|
||||
|
||||
For Windows users, replace $PWD with the full path to your project directory
|
||||
|
||||
|
||||
## Ticketing Integrations:
|
||||
- Jira
|
||||
- Github
|
||||
|
||||
49
go.mod
Normal file
49
go.mod
Normal file
@@ -0,0 +1,49 @@
|
||||
module github.com/strongdm/comply
|
||||
|
||||
go 1.12
|
||||
|
||||
require (
|
||||
github.com/Clever/gitsem v1.0.4
|
||||
github.com/Microsoft/go-winio v0.4.14 // indirect
|
||||
github.com/aktau/github-release v0.8.1
|
||||
github.com/andygrunwald/go-jira v1.12.0
|
||||
github.com/containous/go-bindata v1.0.0
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/docker/distribution v2.7.1+incompatible // indirect
|
||||
github.com/docker/docker v1.13.1
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/docker/go-units v0.4.0 // indirect
|
||||
github.com/elazarl/go-bindata-assetfs v1.0.1
|
||||
github.com/fatih/color v1.9.0
|
||||
github.com/fatih/structs v1.1.0 // indirect
|
||||
github.com/github-release/github-release v0.8.1 // indirect
|
||||
github.com/gohugoio/hugo v0.75.0
|
||||
github.com/google/go-github v17.0.0+incompatible
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/hashicorp/go-retryablehttp v0.6.7 // indirect
|
||||
github.com/inconshreveable/log15 v0.0.0-20200109203555-b30bc20e4fd1 // indirect
|
||||
github.com/jcelliott/lumber v0.0.0-20160324203708-dd349441af25 // indirect
|
||||
github.com/kevinburke/rest v0.0.0-20200429221318-0d2892b400f8 // indirect
|
||||
github.com/lunixbochs/vtclean v1.0.0 // indirect
|
||||
github.com/manifoldco/promptui v0.7.0
|
||||
github.com/mattn/go-colorable v0.1.7 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.9 // indirect
|
||||
github.com/nanobox-io/golang-scribble v0.0.0-20190309225732-aa3e7c118975
|
||||
github.com/olekukonko/tablewriter v0.0.4
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/robfig/cron v1.2.0
|
||||
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966
|
||||
github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 // indirect
|
||||
github.com/trivago/tgo v1.0.7 // indirect
|
||||
github.com/urfave/cli v1.22.4
|
||||
github.com/voxelbrain/goptions v0.0.0-20180630082107-58cddc247ea2 // indirect
|
||||
github.com/xanzy/go-gitlab v0.30.1
|
||||
github.com/yosssi/ace v0.0.5
|
||||
golang.org/x/net v0.0.0-20200904194848-62affa334b73 // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43
|
||||
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 // indirect
|
||||
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e // indirect
|
||||
gopkg.in/blang/semver.v1 v1.1.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.3.0
|
||||
)
|
||||
@@ -7,8 +7,15 @@ import (
|
||||
)
|
||||
|
||||
var serveCommand = cli.Command{
|
||||
Name: "serve",
|
||||
Usage: "live updating version of the build command",
|
||||
Name: "serve",
|
||||
Usage: "live updating version of the build command",
|
||||
Flags: []cli.Flag{
|
||||
cli.IntFlag{
|
||||
Name: "port",
|
||||
Value: 4000,
|
||||
Destination: &render.ServePort,
|
||||
},
|
||||
},
|
||||
Action: serveAction,
|
||||
Before: beforeAll(pandocMustExist, cleanContainers),
|
||||
}
|
||||
|
||||
@@ -99,13 +99,33 @@ func getCfg(cfg map[string]interface{}, k string) (string, error) {
|
||||
return vS, nil
|
||||
}
|
||||
|
||||
func getProjectIssues(g *gitlabPlugin, options *gitlab.ListProjectIssuesOptions) ([]*gitlab.Issue, error) {
|
||||
issues := []*gitlab.Issue{}
|
||||
options.Page = 1
|
||||
|
||||
for {
|
||||
pageIssues, resp, err := g.api().Issues.ListProjectIssues(g.reponame, options)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error retreiving issues from gitlab")
|
||||
}
|
||||
|
||||
issues = append(issues, pageIssues...)
|
||||
|
||||
if resp.CurrentPage >= resp.TotalPages {
|
||||
break
|
||||
}
|
||||
options.Page = resp.NextPage
|
||||
}
|
||||
|
||||
return issues, nil
|
||||
}
|
||||
|
||||
func (g *gitlabPlugin) FindOpen() ([]*model.Ticket, error) {
|
||||
options := &gitlab.ListProjectIssuesOptions{
|
||||
State: gitlab.String("opened"),
|
||||
}
|
||||
|
||||
issues, _, err := g.api().Issues.ListProjectIssues(g.reponame, options)
|
||||
|
||||
issues, err := getProjectIssues(g, options)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error during FindOpen")
|
||||
}
|
||||
@@ -123,10 +143,9 @@ func (g *gitlabPlugin) FindByTagName(name string) ([]*model.Ticket, error) {
|
||||
Labels: []string{name},
|
||||
}
|
||||
|
||||
issues, _, err := g.api().Issues.ListProjectIssues(g.reponame, options)
|
||||
|
||||
issues, err := getProjectIssues(g, options)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error during FindOpen")
|
||||
return nil, errors.Wrap(err, "error during FindByTagName")
|
||||
}
|
||||
|
||||
return toTickets(issues), nil
|
||||
@@ -137,10 +156,11 @@ func (g *gitlabPlugin) LinkFor(t *model.Ticket) string {
|
||||
}
|
||||
|
||||
func (g *gitlabPlugin) Create(ticket *model.Ticket, labels []string) error {
|
||||
l := gitlab.Labels(labels)
|
||||
options := &gitlab.CreateIssueOptions{
|
||||
Title: gitlab.String(ticket.Name),
|
||||
Description: gitlab.String(ticket.Body),
|
||||
Labels: labels,
|
||||
Labels: &l,
|
||||
}
|
||||
_, _, err := g.api().Issues.CreateIssue(g.reponame, options)
|
||||
return err
|
||||
@@ -169,6 +189,15 @@ func toTicket(i *gitlab.Issue) *model.Ticket {
|
||||
if l == "procedure" {
|
||||
t.SetBool("comply-procedure")
|
||||
}
|
||||
|
||||
// seems redundant, but fixes a bug the other two labels introduce
|
||||
// whereby open comply tickets aren't properly accounted for in the UI
|
||||
if l == "comply-audit" {
|
||||
t.SetBool("comply-audit")
|
||||
}
|
||||
if l == "comply-procedure" {
|
||||
t.SetBool("comply-procedure")
|
||||
}
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
@@ -3,7 +3,9 @@ package github
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/google/go-github/github"
|
||||
@@ -95,7 +97,10 @@ func (g *githubPlugin) Configure(cfg map[string]interface{}) error {
|
||||
func getCfg(cfg map[string]interface{}, k string) (string, error) {
|
||||
v, ok := cfg[k]
|
||||
if !ok {
|
||||
return "", errors.New("Missing key: " + k)
|
||||
v = os.Getenv(fmt.Sprintf("GITHUB_%s", strings.ToUpper(k)))
|
||||
if v == "" {
|
||||
return "", errors.New("Missing key: " + k)
|
||||
}
|
||||
}
|
||||
|
||||
vS, ok := v.(string)
|
||||
|
||||
@@ -15,7 +15,10 @@ import (
|
||||
|
||||
const websocketReloader = `<script>
|
||||
(function(){
|
||||
var ws = new WebSocket("ws://localhost:5122/ws")
|
||||
var ws = new WebSocket("ws://localhost:%d/ws")
|
||||
if (location.host != "") {
|
||||
ws = new WebSocket("ws://"+location.host+"/ws")
|
||||
}
|
||||
var connected = false
|
||||
ws.onopen = function(e) {
|
||||
connected = true
|
||||
@@ -74,7 +77,7 @@ func html(output string, live bool, errCh chan error, wg *sync.WaitGroup) {
|
||||
}
|
||||
|
||||
if live {
|
||||
w.Write([]byte(websocketReloader))
|
||||
w.Write([]byte(fmt.Sprintf(websocketReloader, ServePort)))
|
||||
}
|
||||
w.Close()
|
||||
}
|
||||
@@ -82,7 +85,7 @@ func html(output string, live bool, errCh chan error, wg *sync.WaitGroup) {
|
||||
if live {
|
||||
if !opened {
|
||||
opened = true
|
||||
open.Run(filepath.Join(".", "output", "index.html"))
|
||||
open.Run(fmt.Sprintf("http://127.0.0.1:%d/", ServePort))
|
||||
}
|
||||
} else {
|
||||
wg.Done()
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package render
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -11,6 +13,8 @@ import (
|
||||
"github.com/yosssi/ace"
|
||||
)
|
||||
|
||||
var ServePort int
|
||||
|
||||
var upgrader = websocket.Upgrader{
|
||||
ReadBufferSize: 1024,
|
||||
WriteBufferSize: 1024,
|
||||
@@ -87,6 +91,16 @@ func Build(output string, live bool) error {
|
||||
|
||||
if live {
|
||||
watch(errCh)
|
||||
|
||||
go func() {
|
||||
http.Handle("/", http.FileServer(http.Dir(filepath.Join(".", "output"))))
|
||||
err := http.ListenAndServe(fmt.Sprintf("0.0.0.0:%d", ServePort), nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
fmt.Printf("Serving content of output/ at http://127.0.0.1:%d (ctrl-c to quit)\n", ServePort)
|
||||
}
|
||||
// PDF
|
||||
wg.Add(1)
|
||||
|
||||
@@ -45,7 +45,6 @@ func watch(errCh chan error) {
|
||||
}
|
||||
|
||||
http.HandleFunc("/ws", serveWs)
|
||||
go http.ListenAndServe("127.0.0.1:5122", nil)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ func complyBlankReadmeMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-blank/README.md", size: 1965, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-blank/README.md", size: 1965, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -157,7 +157,7 @@ func complyBlankTodoMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-blank/TODO.md", size: 1429, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-blank/TODO.md", size: 1429, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -277,7 +277,7 @@ func complyBlankTemplatesDefaultLatex() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-blank/templates/default.latex", size: 7649, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-blank/templates/default.latex", size: 7649, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -297,7 +297,7 @@ func complyBlankTemplatesIndexAce() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-blank/templates/index.ace", size: 7596, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-blank/templates/index.ace", size: 7596, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -317,7 +317,7 @@ func complySoc2ReadmeMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/README.md", size: 1965, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/README.md", size: 1965, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -337,7 +337,7 @@ func complySoc2TodoMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/TODO.md", size: 1429, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/TODO.md", size: 1429, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -357,7 +357,7 @@ func complySoc2NarrativesReadmeMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/narratives/README.md", size: 96, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/narratives/README.md", size: 96, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -377,7 +377,7 @@ func complySoc2NarrativesControlMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/narratives/control.md", size: 3325, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/narratives/control.md", size: 3325, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -397,7 +397,7 @@ func complySoc2NarrativesOrganizationalMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/narratives/organizational.md", size: 2378, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/narratives/organizational.md", size: 2378, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -417,7 +417,7 @@ func complySoc2NarrativesProductsMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/narratives/products.md", size: 895, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/narratives/products.md", size: 895, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -437,7 +437,7 @@ func complySoc2NarrativesSecurityMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/narratives/security.md", size: 4047, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/narratives/security.md", size: 4047, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -457,7 +457,7 @@ func complySoc2NarrativesSystemMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/narratives/system.md", size: 257, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/narratives/system.md", size: 257, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -477,12 +477,12 @@ func complySoc2PoliciesReadmeMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/README.md", size: 71, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/README.md", size: 71, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _complySoc2PoliciesAccessMd = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x8c\x55\xc1\x6e\x1b\x47\x0c\xbd\xeb\x2b\x08\xe4\xd2\x1a\x91\x5a\xa7\x40\x51\xe8\x96\xba\x05\xec\x02\x45\x0c\x45\x40\xce\xd4\x2c\x57\xcb\x68\x76\xb8\x20\x67\xa5\xca\xa7\xfe\x46\x7f\xaf\x5f\x52\x70\x66\x25\xcb\x6e\xec\xe4\xa4\xdd\x19\x91\x7c\x8f\xef\x91\x9b\xb0\xa7\x25\xbc\x0f\x81\xcc\xe0\x43\xda\x08\x6a\xc3\x69\x0b\x98\x1a\x58\x93\xf6\x9c\x30\xb3\x24\xb8\x97\xc8\xe1\x38\xc3\xa0\x92\x8e\xfd\x12\xde\x7f\x58\xdf\xcf\x0c\x33\x5b\xcb\x64\xcb\x19\xc0\xfa\xe3\x8d\xff\x00\xcc\xe1\xe6\xe6\xe7\xc5\xf5\xc5\xf3\xbb\x8b\xe7\x9f\x66\x3d\x7e\x16\x5d\xd1\x9e\x8d\x25\x95\xd0\x39\x34\x98\x69\x09\x7f\x8c\x09\xae\xe1\xdd\x8f\xd7\xbf\x94\x80\x20\x7d\x4f\x29\x2f\xe1\x2e\x71\x66\x8c\xd0\x48\x18\xfd\x64\x36\x9f\xcf\x67\x6f\xe0\x7e\xd4\x41\x8c\x0a\xd6\x8f\x41\x06\x9a\xcd\x70\x01\xeb\x8e\x60\x98\x6e\xa4\x85\xdc\xb1\xc1\x50\xd0\x43\x16\x68\xa8\xe5\x44\x30\xa8\x04\x6a\x46\x25\xf3\x43\xa9\xbc\x4b\x22\x69\xdb\xfa\x32\x1a\x69\xb9\xcd\x14\xba\xc4\x01\x23\x70\x6a\x15\x2d\xeb\x18\xf2\xa8\x04\x9c\x00\xa1\xc7\x94\x48\x21\x77\x98\xa1\xe7\xc4\x3d\x3f\x78\xd2\x8e\x40\xd9\x76\x8e\x80\x53\x2b\xda\xd7\x36\x46\x31\x03\x51\xa0\xbf\x06\xb1\x51\x69\x01\x13\xe6\x47\x90\x38\x0c\x91\x2b\x2e\x8c\xf1\xe5\xea\x07\xce\x1d\xa7\x52\x49\x74\x8b\x89\x1f\x4a\x89\xaf\x67\x6c\xc7\x18\xe7\x99\xfb\xda\xb8\x01\x35\xd7\x37\xea\x87\x28\x47\x22\x2b\xe7\x41\x52\x56\x0c\x59\xd4\x3c\xe5\x1b\xf8\x15\xc3\x6e\xab\x32\xa6\xa6\x14\xb8\x4b\x20\xda\x38\x73\x39\xf3\xfe\x66\xda\xf0\x5d\xab\xd2\xc3\x46\x72\x07\x9c\x8c\x9b\x8a\x45\xc6\x5c\x9e\x9f\x73\xfa\xfe\xed\xff\x8e\x80\x0d\x94\x22\x63\xca\x20\xb5\x0b\x83\x72\x0a\x3c\xc4\x22\x7b\x24\xb4\xec\x47\x7b\x8e\xb4\xa5\x85\x5b\x5c\xc6\x94\x21\x28\xd5\x04\x85\xbc\x3b\xdc\xac\x40\xa4\x3d\x45\x03\x54\x02\x25\xcb\xca\x21\x53\x53\xcd\x11\x8f\x95\x18\x99\x8c\x1a\xbc\x3f\x1b\x93\x38\x66\x8a\x47\x48\x44\x4d\xfd\xdf\x40\xea\x84\x81\x30\x74\xfe\x62\x92\xfe\xfd\xfb\x1f\x83\xcf\xb2\x81\x66\xcc\x4c\xb6\x80\x4f\x1d\xb9\x67\xdc\x5a\xe5\x4e\x25\xbe\x28\x24\x84\x0e\xd3\x96\xcc\xb9\x17\x97\x57\x02\xf6\x0a\xf0\x1a\xd1\xfc\xa0\xb4\x97\x5d\x45\xd5\x72\x2e\x99\x13\x1d\x6a\x35\x8f\x6e\xd8\x70\x13\xa9\x81\x83\xe3\xf1\x6b\x47\xe4\x3d\xdb\x4f\xde\x7d\x02\x04\x63\x96\x2d\xe5\x8e\xb4\x3a\x61\xda\x05\xee\x82\xab\xdf\x46\xf5\x75\x21\xe7\xcd\xb1\xbc\x9a\x95\xe1\xe5\x05\xdc\x72\xb9\xfb\x13\x13\x6e\x49\x27\x43\x18\xdc\xae\x60\x1c\x24\x41\xc7\x5a\xa4\xc2\x02\xee\xe4\xbe\xc5\x63\xf8\x0a\xa8\x47\x8e\x06\x77\x6b\xa7\x52\xe3\x1d\x5e\xff\x18\x56\x92\x38\xa7\xdc\x11\x6b\xa1\xe8\x20\xa7\x14\x77\xeb\xaa\xb7\x6b\x06\xa1\xa3\xb0\x8b\x6c\xb9\x44\xbf\xde\xcd\x49\xd6\x56\xa6\xc9\x7e\x96\xd7\x77\x8c\x1c\x7c\xee\xa5\xad\x82\x9f\xcc\x01\x4a\x7b\xa6\x43\xcd\x8b\xc3\xa0\xe2\x2d\xc5\x2f\x99\xcf\xfb\x3c\x43\x33\x09\x8c\xee\xb5\x47\x14\xf6\x94\xc2\x41\x74\x67\xc5\x26\x55\x9b\x2f\x17\xce\x02\x46\x19\xc6\xe1\x2c\xe8\xb4\x0a\xce\x1a\x4d\x9b\xed\x55\x91\x92\x64\xf6\x8d\xee\xdd\x2f\xee\xc0\x74\x96\x06\x3a\x34\xd8\x90\x5b\x66\xfa\x32\x50\x73\x81\xf4\x76\x05\x46\xa9\xf1\x56\x1f\x88\x76\xf1\x58\xe5\x03\xa5\x41\x34\x3b\xbe\xbb\x35\xd8\xd8\xf7\xa8\xfc\xe0\x35\x4f\x5a\x4c\x9b\xf6\x9c\xb3\x74\x87\x53\x5d\x75\x27\xf5\x27\xcf\x4e\x3a\x63\xf9\x60\x3d\x6d\xd3\x39\x81\x4d\xd7\xa7\xc9\x6a\x79\x4f\xb0\x19\x8d\x93\x1f\x36\x78\x34\x28\xeb\x47\x29\x10\x0f\x05\x42\xa5\x1d\x2e\x37\xe8\xd5\xa7\xe7\xf4\xa7\x81\x2c\x66\xb0\x97\xc6\xf6\xe5\xd6\x1e\x38\xc6\x93\x89\x6f\x57\xd5\xc2\x35\xa5\x7f\x49\x8a\xc3\x4a\xe4\x45\x3f\xbd\x11\x6e\x00\x8f\x6c\x25\x46\x39\x94\x7a\x86\x3d\x81\x65\x1a\x0c\xd0\x7c\x6b\x46\x4e\xe4\x2d\xab\x68\x9e\x7e\xc5\x2f\x64\xbf\xf8\xec\x9d\x48\xae\x8a\x5d\x5f\x99\x08\xbb\x20\xf4\xbb\x1b\xae\x97\x94\xbb\xb7\x0e\xcb\xff\xe8\x36\x71\x74\xd5\xf6\x5f\x1b\x2b\x9f\x27\x0c\x61\x54\x0c\x47\x47\x30\xfb\x2f\x00\x00\xff\xff\x29\x19\x25\xcc\x7f\x08\x00\x00")
|
||||
var _complySoc2PoliciesAccessMd = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x8c\x55\xc1\x6e\x1b\x47\x0c\xbd\xeb\x2b\x08\xe4\xd2\x1a\x91\x5a\xa7\x40\x51\xe8\x96\xba\x05\xec\x02\x45\x0c\x45\x40\xce\xd4\x2c\x57\xcb\x68\x76\xb8\x20\x67\xa5\xca\xa7\xfe\x46\x7f\xaf\x5f\x52\x70\x66\x25\xcb\x6e\xec\xe4\xa4\xdd\x19\x91\x7c\x8f\xef\x91\x9b\xb0\xa7\x25\xbc\x0f\x81\xcc\xe0\x43\xda\x08\x6a\xc3\x69\x0b\x98\x1a\x58\x93\xf6\x9c\x30\xb3\x24\xb8\x97\xc8\xe1\x38\xc3\xa0\x92\x8e\xfd\x12\xde\x7f\x58\xdf\xcf\x0c\x33\x5b\xcb\x64\xcb\x19\xc0\xfa\xe3\x8d\xff\x00\xcc\xe1\xe6\xe6\xe7\xc5\xf5\xc5\xf3\xbb\x8b\xe7\x9f\x66\x3d\x7e\x16\x5d\xd1\x9e\x8d\x25\x95\xd0\x39\x34\x98\x69\x09\x7f\x8c\x09\xae\xe1\xdd\x8f\xd7\xbf\x94\x80\x20\x7d\x4f\x29\x2f\xe1\x2e\x71\x66\x8c\xd0\x48\x18\xfd\x64\x36\x9f\xcf\x67\x6f\xe0\x7e\xd4\x41\x8c\x0a\xd6\x8f\x41\x06\x9a\xcd\x70\x01\xeb\x8e\x60\x98\x6e\xa4\x85\xdc\xb1\xc1\x50\xd0\x03\x1b\x64\x81\x86\x5a\x4e\x04\x83\x4a\xa0\x66\x54\x2a\x87\x52\xa9\x97\x5c\xd2\xb6\xf5\x65\x34\xd2\x72\x9b\x29\x74\x89\x03\x46\xe0\xd4\x2a\x5a\xd6\x31\xe4\x51\x09\x38\x01\x42\x8f\x29\x91\x42\xee\x30\x43\xcf\x89\x7b\x7e\xf0\xa4\x1d\x81\xb2\xed\x1c\x04\xa7\x56\xb4\xaf\x9d\x8c\x62\x06\xa2\x40\x7f\x0d\x62\xa3\xd2\x02\x26\xd8\x8f\x38\x71\x18\x22\x57\x5c\x18\xe3\xcb\xd5\x0f\x9c\x3b\x4e\xa5\x92\xe8\x16\x13\x3f\x94\x12\x5f\xcf\xd8\x8e\x31\xce\x33\xf7\xb5\x77\x03\x6a\xae\x6f\xd4\x0f\x51\x8e\x44\x56\xce\x83\xa4\xac\x18\xb2\xa8\x79\xca\x37\xf0\x2b\x86\xdd\x56\x65\x4c\x4d\x29\x70\x97\x40\xb4\x71\xe6\x72\xe6\xfd\xcd\xb4\xe1\xbb\x56\xa5\x87\x8d\xe4\x0e\x38\x19\x37\x15\x8b\x8c\xb9\x3c\x3f\xe7\xf4\xfd\xdb\xff\x1d\xb9\x9c\x4a\x91\x31\x65\x90\xda\x85\x41\x39\x05\x1e\x62\x51\x3e\x12\x5a\xf6\xa3\x3d\x47\xda\xd2\xc2\x5d\x2e\x63\xca\x10\x94\x6a\x82\x42\xde\x4d\x6e\x56\x20\xd2\x9e\xa2\x01\x2a\x81\x92\x65\xe5\x90\xa9\xa9\xe6\x88\xc7\x4a\x8c\x4c\x46\x0d\xde\x9f\x8d\x49\x1c\x33\xc5\x23\x24\xa2\xa6\xfe\x6f\x20\x75\xc2\x40\x18\x3a\x7f\x31\x49\xff\xfe\xfd\x8f\xc1\x67\xd9\x40\x33\x66\x26\x5b\xc0\xa7\x8e\xdc\x33\x6e\xad\x72\xa7\x12\x5f\x14\x12\x42\x87\x69\x4b\xe6\xdc\x8b\xd1\x2b\x01\x7b\x05\x78\x8d\x68\x7e\x50\xda\xcb\xae\xa2\x6a\x39\x97\xcc\x89\x0e\xb5\x9a\x47\x37\x6c\xb8\x89\xd4\xc0\xc1\xf1\xf8\xb5\x23\xf2\x9e\xed\x27\xef\x3e\x01\x82\x31\xcb\x96\x72\x47\x5a\x9d\x30\xad\x03\x77\xc1\xd5\x6f\xa3\xfa\xc6\x90\xf3\xf2\x58\x5e\xcd\xca\xfc\xf2\x02\x6e\xb9\xdc\xfd\x89\x09\xb7\xa4\x93\x21\x0c\x6e\x57\x30\x0e\x92\xa0\x63\x2d\x52\x61\x01\x77\x72\xdf\xe2\x31\x7c\x05\xd4\x23\x47\x83\xbb\xb5\x53\xa9\xf1\x0e\xaf\x7f\x0c\x2b\x49\x9c\x53\xee\x88\xb5\x50\x74\x90\x53\x8a\xbb\x75\xd5\xdb\x35\x83\xd0\x51\xd8\x45\xb6\x5c\xa2\x5f\xef\xe6\x24\x6b\x2b\xd3\x64\x3f\xcb\xeb\x6b\x46\x0e\x3e\xf7\xd2\x56\xc1\x4f\xe6\x00\xa5\x3d\xd3\xa1\xe6\xc5\x61\x50\xf1\x96\xe2\x97\xcc\xe7\x7d\x9e\xa1\x99\x04\x46\xf7\xda\x23\x0a\x7b\x4a\xe1\x20\xba\xb3\x62\x93\xaa\xcd\x97\x0b\x67\x01\xa3\x0c\xe3\x70\x16\x74\x5a\x05\x67\x8d\xa6\xcd\xf6\xaa\x48\x49\x32\xfb\x52\xf7\xee\x17\x77\x60\x3a\x4b\x03\x1d\x1a\x6c\xc8\x2d\x33\x7d\x1c\xa8\xb9\x40\x7a\xbb\x02\xa3\xd4\x78\xab\x0f\x44\xbb\x78\xac\xf2\x81\xd2\x20\x9a\x1d\xdf\xdd\x1a\x6c\xec\x7b\x54\x7e\xf0\x9a\x27\x2d\xa6\x4d\x7b\xce\x59\xba\xc3\xa9\xae\xba\x93\xfa\x93\x67\x27\x9d\xb1\x7c\xb3\x9e\xb6\xe9\x9c\xc0\xa6\xeb\xd3\x64\xb5\xbc\x27\xd8\x8c\xc6\xc9\x0f\x1b\x3c\x1a\x94\xf5\xa3\x14\x88\x87\x02\xa1\xd2\x0e\x97\x1b\xf4\xea\xd3\x73\xfa\xd3\x40\x16\x33\xd8\x4b\x63\xfb\x72\x6b\x0f\x1c\xe3\xc9\xc4\xb7\xab\x6a\xe1\x9a\xd2\xbf\x24\xc5\x61\x25\xf2\xa2\x9f\xde\x08\x37\x80\x47\xb6\x12\xa3\x1c\x4a\x3d\xc3\x9e\xc0\x32\x0d\x06\x68\xbe\x35\x23\x27\xf2\x96\x55\x34\x4f\x3f\xe4\x17\xb2\x5f\x7c\xf6\x4e\x24\x57\xc5\xae\xaf\x4c\x84\x5d\x10\xfa\xdd\x0d\xd7\x4b\xca\xdd\x5b\x87\xe5\x7f\x74\x9b\x38\xba\x6a\xfb\xaf\x8d\x95\xcf\x13\x86\x30\x2a\x86\xa3\x23\x98\xfd\x17\x00\x00\xff\xff\x61\xc4\x99\x8a\x82\x08\x00\x00")
|
||||
|
||||
func complySoc2PoliciesAccessMdBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
@@ -497,7 +497,7 @@ func complySoc2PoliciesAccessMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/access.md", size: 2175, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/access.md", size: 2178, mode: os.FileMode(420), modTime: time.Unix(1545087106, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -517,7 +517,7 @@ func complySoc2PoliciesApplicationMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/application.md", size: 8377, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/application.md", size: 8377, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -537,7 +537,7 @@ func complySoc2PoliciesAvailabilityMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/availability.md", size: 7019, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/availability.md", size: 7019, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -557,7 +557,7 @@ func complySoc2PoliciesChangeMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/change.md", size: 2793, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/change.md", size: 2793, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -577,7 +577,7 @@ func complySoc2PoliciesClassificationMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/classification.md", size: 14376, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/classification.md", size: 14376, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -597,7 +597,7 @@ func complySoc2PoliciesConductMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/conduct.md", size: 4492, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/conduct.md", size: 4492, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -617,7 +617,7 @@ func complySoc2PoliciesConfidentialityMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/confidentiality.md", size: 3653, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/confidentiality.md", size: 3653, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -637,7 +637,7 @@ func complySoc2PoliciesContinuityMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/continuity.md", size: 5043, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/continuity.md", size: 5043, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -657,7 +657,7 @@ func complySoc2PoliciesCyberMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/cyber.md", size: 4805, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/cyber.md", size: 4805, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -677,7 +677,7 @@ func complySoc2PoliciesDatacenterMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/datacenter.md", size: 3014, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/datacenter.md", size: 3014, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -697,7 +697,7 @@ func complySoc2PoliciesDevelopmentMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/development.md", size: 8933, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/development.md", size: 8933, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -717,7 +717,7 @@ func complySoc2PoliciesDisasterMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/disaster.md", size: 10315, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/disaster.md", size: 10315, mode: os.FileMode(420), modTime: time.Unix(1545087106, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -737,7 +737,7 @@ func complySoc2PoliciesEncryptionMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/encryption.md", size: 5381, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/encryption.md", size: 5381, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -757,7 +757,7 @@ func complySoc2PoliciesIncidentMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/incident.md", size: 8552, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/incident.md", size: 8552, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -777,7 +777,7 @@ func complySoc2PoliciesInformationMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/information.md", size: 5359, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/information.md", size: 5359, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -797,7 +797,7 @@ func complySoc2PoliciesLogMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/log.md", size: 4307, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/log.md", size: 4307, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -817,7 +817,7 @@ func complySoc2PoliciesMediaMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/media.md", size: 8819, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/media.md", size: 8819, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -837,7 +837,7 @@ func complySoc2PoliciesOfficeMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/office.md", size: 3927, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/office.md", size: 3927, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -857,7 +857,7 @@ func complySoc2PoliciesPasswordMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/password.md", size: 1796, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/password.md", size: 1796, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -877,7 +877,7 @@ func complySoc2PoliciesPolicyMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/policy.md", size: 892, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/policy.md", size: 892, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -897,7 +897,7 @@ func complySoc2PoliciesPrivacyMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/privacy.md", size: 346, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/privacy.md", size: 346, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -917,7 +917,7 @@ func complySoc2PoliciesProcessingMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/processing.md", size: 210, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/processing.md", size: 210, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -937,7 +937,7 @@ func complySoc2PoliciesRemoteMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/remote.md", size: 4119, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/remote.md", size: 4119, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -957,7 +957,7 @@ func complySoc2PoliciesRetentionMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/retention.md", size: 6811, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/retention.md", size: 6811, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -977,7 +977,7 @@ func complySoc2PoliciesRiskMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/risk.md", size: 10486, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/risk.md", size: 10486, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -997,7 +997,7 @@ func complySoc2PoliciesVendorMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/vendor.md", size: 3139, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/vendor.md", size: 3139, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -1017,7 +1017,7 @@ func complySoc2PoliciesWorkstationMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/workstation.md", size: 1791, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/policies/workstation.md", size: 1791, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -1037,7 +1037,7 @@ func complySoc2ProceduresReadmeMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/procedures/README.md", size: 92, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/procedures/README.md", size: 92, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -1057,7 +1057,7 @@ func complySoc2ProceduresOffboardingMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/procedures/offboarding.md", size: 358, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/procedures/offboarding.md", size: 358, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -1077,7 +1077,7 @@ func complySoc2ProceduresOnboardingMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/procedures/onboarding.md", size: 495, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/procedures/onboarding.md", size: 495, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -1097,7 +1097,7 @@ func complySoc2ProceduresPatchMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/procedures/patch.md", size: 380, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/procedures/patch.md", size: 380, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -1117,7 +1117,7 @@ func complySoc2ProceduresWorkstationMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/procedures/workstation.md", size: 1081, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/procedures/workstation.md", size: 1081, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -1137,7 +1137,7 @@ func complySoc2StandardsReadmeMd() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/standards/README.md", size: 282, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/standards/README.md", size: 282, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -1157,7 +1157,7 @@ func complySoc2StandardsTsc2017Yml() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/standards/TSC-2017.yml", size: 16305, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/standards/TSC-2017.yml", size: 16305, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -1177,7 +1177,7 @@ func complySoc2TemplatesDefaultLatex() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/templates/default.latex", size: 7649, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/templates/default.latex", size: 7649, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -1197,7 +1197,7 @@ func complySoc2TemplatesIndexAce() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "comply-soc2/templates/index.ace", size: 7596, mode: os.FileMode(420), modTime: time.Unix(1541743836, 0)}
|
||||
info := bindataFileInfo{name: "comply-soc2/templates/index.ace", size: 7596, mode: os.FileMode(420), modTime: time.Unix(1545086630, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
10
tools.go
Normal file
10
tools.go
Normal file
@@ -0,0 +1,10 @@
|
||||
// +build tools
|
||||
|
||||
package tools
|
||||
|
||||
import (
|
||||
_ "github.com/Clever/gitsem"
|
||||
_ "github.com/aktau/github-release"
|
||||
_ "github.com/containous/go-bindata/go-bindata" // v1.0.0
|
||||
_ "github.com/elazarl/go-bindata-assetfs/go-bindata-assetfs" // v0.0.0-20170227122030-30f82fa23fd8
|
||||
)
|
||||
24
vendor/github.com/Clever/gitsem/.drone.yml
generated
vendored
Normal file
24
vendor/github.com/Clever/gitsem/.drone.yml
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
image: bradrydzewski/go:1.3
|
||||
script:
|
||||
- make test
|
||||
notify:
|
||||
email:
|
||||
recipients:
|
||||
- drone@clever.com
|
||||
hipchat:
|
||||
room: Clever-Dev-CI
|
||||
token: {{hipchat_token}}
|
||||
on_started: true
|
||||
on_success: true
|
||||
on_failure: true
|
||||
publish:
|
||||
github:
|
||||
branch: master
|
||||
script:
|
||||
- make release
|
||||
artifacts:
|
||||
- release
|
||||
tag: v$(cat VERSION)
|
||||
token: {{github_token}}
|
||||
user: Clever
|
||||
repo: gitsem
|
||||
25
vendor/github.com/Clever/gitsem/.gitignore
generated
vendored
Normal file
25
vendor/github.com/Clever/gitsem/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
*.test
|
||||
|
||||
gitsem
|
||||
54
vendor/github.com/Clever/gitsem/Makefile
generated
vendored
Normal file
54
vendor/github.com/Clever/gitsem/Makefile
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
SHELL := /bin/bash
|
||||
PKG = github.com/Clever/gitsem
|
||||
PKGS = $(PKG)
|
||||
VERSION := $(shell cat VERSION)
|
||||
EXECUTABLE := gitsem
|
||||
BUILDS := \
|
||||
build/$(EXECUTABLE)-v$(VERSION)-darwin-amd64 \
|
||||
build/$(EXECUTABLE)-v$(VERSION)-linux-amd64 \
|
||||
build/$(EXECUTABLE)-v$(VERSION)-windows-amd64
|
||||
COMPRESSED_BUILDS := $(BUILDS:%=%.tar.gz)
|
||||
RELEASE_ARTIFACTS := $(COMPRESSED_BUILDS:build/%=release/%)
|
||||
|
||||
.PHONY: test golint
|
||||
|
||||
golint:
|
||||
@go get github.com/golang/lint/golint
|
||||
|
||||
test: $(PKGS)
|
||||
|
||||
$(PKGS): golint
|
||||
@go get -d -t $@
|
||||
@gofmt -w=true $(GOPATH)/src/$@*/**.go
|
||||
ifneq ($(NOLINT),1)
|
||||
@echo "LINTING..."
|
||||
@PATH=$(PATH):$(GOPATH)/bin golint $(GOPATH)/src/$@*/**.go
|
||||
@echo ""
|
||||
endif
|
||||
ifeq ($(COVERAGE),1)
|
||||
@go test -cover -coverprofile=$(GOPATH)/src/$@/c.out $@ -test.v
|
||||
@go tool cover -html=$(GOPATH)/src/$@/c.out
|
||||
else
|
||||
@echo "TESTING..."
|
||||
@go test $@ -test.v
|
||||
endif
|
||||
|
||||
run:
|
||||
@go run main.go
|
||||
|
||||
build/$(EXECUTABLE)-v$(VERSION)-darwin-amd64:
|
||||
GOARCH=amd64 GOOS=darwin go build -o "$@/$(EXECUTABLE)"
|
||||
build/$(EXECUTABLE)-v$(VERSION)-linux-amd64:
|
||||
GOARCH=amd64 GOOS=linux go build -o "$@/$(EXECUTABLE)"
|
||||
build/$(EXECUTABLE)-v$(VERSION)-windows-amd64:
|
||||
GOARCH=amd64 GOOS=windows go build -o "$@/$(EXECUTABLE).exe"
|
||||
build: $(BUILDS)
|
||||
%.tar.gz: %
|
||||
tar -C `dirname $<` -zcvf "$<.tar.gz" `basename $<`
|
||||
$(RELEASE_ARTIFACTS): release/% : build/%
|
||||
mkdir -p release
|
||||
cp $< $@
|
||||
release: $(RELEASE_ARTIFACTS)
|
||||
|
||||
clean:
|
||||
rm -rf build release
|
||||
34
vendor/github.com/Clever/gitsem/README.md
generated
vendored
Normal file
34
vendor/github.com/Clever/gitsem/README.md
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
# gitsem
|
||||
|
||||
A command line utility for managing semantically versioned (semver) git tags.
|
||||
|
||||
Run this in a git repository to bump the version and write the new data back to the VERSION file.
|
||||
It will also create a version commit and (optional) tag, and fail if the repo is not clean.
|
||||
|
||||
## Installation
|
||||
|
||||
```shell
|
||||
$ go get github.com/Clever/gitsem
|
||||
```
|
||||
|
||||
## Example
|
||||
```shell
|
||||
$ gitsem patch
|
||||
$ gitsem -m "Upgrade to %s for reasons" patch
|
||||
$ gitsem minor
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```shell
|
||||
gitsem [options] version
|
||||
```
|
||||
|
||||
`version` can be one of: `newversion | patch | minor | major`
|
||||
|
||||
The version argument should be a valid semver string, or a field of a semver string (one of "patch", "minor", or "major").
|
||||
In the second case, the existing version will be incremented by 1 in the specified field.
|
||||
|
||||
### Options
|
||||
- `m=%s` specifies a commit message to use when bumping the version. If %s appears, it will be replaced with the new version number.
|
||||
- `tag=true` whether or not to create a tag at the version commit
|
||||
1
vendor/github.com/Clever/gitsem/VERSION
generated
vendored
Normal file
1
vendor/github.com/Clever/gitsem/VERSION
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
1.0.4
|
||||
39
vendor/github.com/Clever/gitsem/git.go
generated
vendored
Normal file
39
vendor/github.com/Clever/gitsem/git.go
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func isRepoClean() (bool, error) {
|
||||
cmd := exec.Command("git", "status", "-s")
|
||||
result := &bytes.Buffer{}
|
||||
cmd.Stdout = result
|
||||
if err := cmd.Run(); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return result.String() == "", nil
|
||||
}
|
||||
|
||||
func repoRoot() (string, error) {
|
||||
cmd := exec.Command("git", "rev-parse", "--show-toplevel")
|
||||
result := &bytes.Buffer{}
|
||||
cmd.Stdout = result
|
||||
if err := cmd.Run(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return strings.TrimSpace(result.String()), nil
|
||||
}
|
||||
|
||||
func addFile(path string) error {
|
||||
return exec.Command("git", "add", path).Run()
|
||||
}
|
||||
|
||||
func commit(message string) error {
|
||||
return exec.Command("git", "commit", "-m", message).Run()
|
||||
}
|
||||
|
||||
func tag(version string) error {
|
||||
return exec.Command("git", "tag", version).Run()
|
||||
}
|
||||
126
vendor/github.com/Clever/gitsem/main.go
generated
vendored
Normal file
126
vendor/github.com/Clever/gitsem/main.go
generated
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"gopkg.in/blang/semver.v1"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func commitMessage(message, version string) string {
|
||||
if strings.Contains(message, "%s") {
|
||||
return fmt.Sprintf(message, version)
|
||||
}
|
||||
return message
|
||||
}
|
||||
|
||||
func getCurrentVersion(path string) (*semver.Version, error) {
|
||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||
return &semver.Version{}, nil
|
||||
}
|
||||
contents, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return semver.New(strings.TrimSpace(string(contents)))
|
||||
}
|
||||
|
||||
const versionFileName = "VERSION"
|
||||
|
||||
func exitWithError(message string) {
|
||||
fmt.Fprintf(os.Stderr, message+"\n\n")
|
||||
flag.Usage()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func bump(old *semver.Version, part string) *semver.Version {
|
||||
// We don't want to mutate the input, but there's no Clone or Copy method on a semver.Version,
|
||||
// so we make a new one by parsing the string version of the old one.
|
||||
// We ignore any errors because we know it's valid semver.
|
||||
new, _ := semver.New(old.String())
|
||||
switch part {
|
||||
case "major":
|
||||
new.Major++
|
||||
new.Minor = 0
|
||||
new.Patch = 0
|
||||
case "minor":
|
||||
new.Minor++
|
||||
new.Patch = 0
|
||||
case "patch":
|
||||
new.Patch++
|
||||
}
|
||||
return new
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Usage = func() {
|
||||
fmt.Fprintf(os.Stderr, "Usage of %s: [options] version\n\n", os.Args[0])
|
||||
fmt.Fprintf(os.Stderr, "version can be one of: newversion | patch | minor | major\n\n")
|
||||
fmt.Fprintf(os.Stderr, "options:\n")
|
||||
flag.PrintDefaults()
|
||||
}
|
||||
message := flag.String("m", "%s", "commit message for version commit")
|
||||
help := flag.Bool("h", false, "print usage and exit")
|
||||
shouldTag := flag.Bool("tag", true, "whether or not to make a tag at the version commit")
|
||||
flag.Parse()
|
||||
|
||||
if *help {
|
||||
flag.Usage()
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if *message == "" {
|
||||
exitWithError("missing message")
|
||||
}
|
||||
|
||||
if clean, err := isRepoClean(); err != nil {
|
||||
log.Fatal(err)
|
||||
} else if !clean {
|
||||
log.Fatal("repo isn't clean")
|
||||
}
|
||||
|
||||
root, err := repoRoot()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
versionFile := filepath.Join(root, versionFileName)
|
||||
version, err := getCurrentVersion(versionFile)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if len(flag.Args()) != 1 {
|
||||
exitWithError("gitsem takes exactly one non-flag argument: version")
|
||||
}
|
||||
|
||||
newVersion := flag.Args()[0]
|
||||
switch newVersion {
|
||||
case "patch", "minor", "major":
|
||||
version = bump(version, newVersion)
|
||||
default:
|
||||
if version, err = semver.New(newVersion); err != nil {
|
||||
log.Fatalf("failed to parse %s as semver: %s", newVersion, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
if err := ioutil.WriteFile(versionFile, []byte(version.String()), 0666); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err := addFile(versionFile); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
versionString := "v" + version.String()
|
||||
*message = commitMessage(*message, versionString)
|
||||
if err := commit(*message); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if *shouldTag {
|
||||
if err := tag(versionString); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
fmt.Println(versionString)
|
||||
}
|
||||
274
vendor/github.com/Microsoft/go-winio/ea.go
generated
vendored
274
vendor/github.com/Microsoft/go-winio/ea.go
generated
vendored
@@ -1,137 +1,137 @@
|
||||
package winio
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
)
|
||||
|
||||
type fileFullEaInformation struct {
|
||||
NextEntryOffset uint32
|
||||
Flags uint8
|
||||
NameLength uint8
|
||||
ValueLength uint16
|
||||
}
|
||||
|
||||
var (
|
||||
fileFullEaInformationSize = binary.Size(&fileFullEaInformation{})
|
||||
|
||||
errInvalidEaBuffer = errors.New("invalid extended attribute buffer")
|
||||
errEaNameTooLarge = errors.New("extended attribute name too large")
|
||||
errEaValueTooLarge = errors.New("extended attribute value too large")
|
||||
)
|
||||
|
||||
// ExtendedAttribute represents a single Windows EA.
|
||||
type ExtendedAttribute struct {
|
||||
Name string
|
||||
Value []byte
|
||||
Flags uint8
|
||||
}
|
||||
|
||||
func parseEa(b []byte) (ea ExtendedAttribute, nb []byte, err error) {
|
||||
var info fileFullEaInformation
|
||||
err = binary.Read(bytes.NewReader(b), binary.LittleEndian, &info)
|
||||
if err != nil {
|
||||
err = errInvalidEaBuffer
|
||||
return
|
||||
}
|
||||
|
||||
nameOffset := fileFullEaInformationSize
|
||||
nameLen := int(info.NameLength)
|
||||
valueOffset := nameOffset + int(info.NameLength) + 1
|
||||
valueLen := int(info.ValueLength)
|
||||
nextOffset := int(info.NextEntryOffset)
|
||||
if valueLen+valueOffset > len(b) || nextOffset < 0 || nextOffset > len(b) {
|
||||
err = errInvalidEaBuffer
|
||||
return
|
||||
}
|
||||
|
||||
ea.Name = string(b[nameOffset : nameOffset+nameLen])
|
||||
ea.Value = b[valueOffset : valueOffset+valueLen]
|
||||
ea.Flags = info.Flags
|
||||
if info.NextEntryOffset != 0 {
|
||||
nb = b[info.NextEntryOffset:]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DecodeExtendedAttributes decodes a list of EAs from a FILE_FULL_EA_INFORMATION
|
||||
// buffer retrieved from BackupRead, ZwQueryEaFile, etc.
|
||||
func DecodeExtendedAttributes(b []byte) (eas []ExtendedAttribute, err error) {
|
||||
for len(b) != 0 {
|
||||
ea, nb, err := parseEa(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
eas = append(eas, ea)
|
||||
b = nb
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func writeEa(buf *bytes.Buffer, ea *ExtendedAttribute, last bool) error {
|
||||
if int(uint8(len(ea.Name))) != len(ea.Name) {
|
||||
return errEaNameTooLarge
|
||||
}
|
||||
if int(uint16(len(ea.Value))) != len(ea.Value) {
|
||||
return errEaValueTooLarge
|
||||
}
|
||||
entrySize := uint32(fileFullEaInformationSize + len(ea.Name) + 1 + len(ea.Value))
|
||||
withPadding := (entrySize + 3) &^ 3
|
||||
nextOffset := uint32(0)
|
||||
if !last {
|
||||
nextOffset = withPadding
|
||||
}
|
||||
info := fileFullEaInformation{
|
||||
NextEntryOffset: nextOffset,
|
||||
Flags: ea.Flags,
|
||||
NameLength: uint8(len(ea.Name)),
|
||||
ValueLength: uint16(len(ea.Value)),
|
||||
}
|
||||
|
||||
err := binary.Write(buf, binary.LittleEndian, &info)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = buf.Write([]byte(ea.Name))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = buf.WriteByte(0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = buf.Write(ea.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = buf.Write([]byte{0, 0, 0}[0 : withPadding-entrySize])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// EncodeExtendedAttributes encodes a list of EAs into a FILE_FULL_EA_INFORMATION
|
||||
// buffer for use with BackupWrite, ZwSetEaFile, etc.
|
||||
func EncodeExtendedAttributes(eas []ExtendedAttribute) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
for i := range eas {
|
||||
last := false
|
||||
if i == len(eas)-1 {
|
||||
last = true
|
||||
}
|
||||
|
||||
err := writeEa(&buf, &eas[i], last)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
package winio
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
)
|
||||
|
||||
type fileFullEaInformation struct {
|
||||
NextEntryOffset uint32
|
||||
Flags uint8
|
||||
NameLength uint8
|
||||
ValueLength uint16
|
||||
}
|
||||
|
||||
var (
|
||||
fileFullEaInformationSize = binary.Size(&fileFullEaInformation{})
|
||||
|
||||
errInvalidEaBuffer = errors.New("invalid extended attribute buffer")
|
||||
errEaNameTooLarge = errors.New("extended attribute name too large")
|
||||
errEaValueTooLarge = errors.New("extended attribute value too large")
|
||||
)
|
||||
|
||||
// ExtendedAttribute represents a single Windows EA.
|
||||
type ExtendedAttribute struct {
|
||||
Name string
|
||||
Value []byte
|
||||
Flags uint8
|
||||
}
|
||||
|
||||
func parseEa(b []byte) (ea ExtendedAttribute, nb []byte, err error) {
|
||||
var info fileFullEaInformation
|
||||
err = binary.Read(bytes.NewReader(b), binary.LittleEndian, &info)
|
||||
if err != nil {
|
||||
err = errInvalidEaBuffer
|
||||
return
|
||||
}
|
||||
|
||||
nameOffset := fileFullEaInformationSize
|
||||
nameLen := int(info.NameLength)
|
||||
valueOffset := nameOffset + int(info.NameLength) + 1
|
||||
valueLen := int(info.ValueLength)
|
||||
nextOffset := int(info.NextEntryOffset)
|
||||
if valueLen+valueOffset > len(b) || nextOffset < 0 || nextOffset > len(b) {
|
||||
err = errInvalidEaBuffer
|
||||
return
|
||||
}
|
||||
|
||||
ea.Name = string(b[nameOffset : nameOffset+nameLen])
|
||||
ea.Value = b[valueOffset : valueOffset+valueLen]
|
||||
ea.Flags = info.Flags
|
||||
if info.NextEntryOffset != 0 {
|
||||
nb = b[info.NextEntryOffset:]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DecodeExtendedAttributes decodes a list of EAs from a FILE_FULL_EA_INFORMATION
|
||||
// buffer retrieved from BackupRead, ZwQueryEaFile, etc.
|
||||
func DecodeExtendedAttributes(b []byte) (eas []ExtendedAttribute, err error) {
|
||||
for len(b) != 0 {
|
||||
ea, nb, err := parseEa(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
eas = append(eas, ea)
|
||||
b = nb
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func writeEa(buf *bytes.Buffer, ea *ExtendedAttribute, last bool) error {
|
||||
if int(uint8(len(ea.Name))) != len(ea.Name) {
|
||||
return errEaNameTooLarge
|
||||
}
|
||||
if int(uint16(len(ea.Value))) != len(ea.Value) {
|
||||
return errEaValueTooLarge
|
||||
}
|
||||
entrySize := uint32(fileFullEaInformationSize + len(ea.Name) + 1 + len(ea.Value))
|
||||
withPadding := (entrySize + 3) &^ 3
|
||||
nextOffset := uint32(0)
|
||||
if !last {
|
||||
nextOffset = withPadding
|
||||
}
|
||||
info := fileFullEaInformation{
|
||||
NextEntryOffset: nextOffset,
|
||||
Flags: ea.Flags,
|
||||
NameLength: uint8(len(ea.Name)),
|
||||
ValueLength: uint16(len(ea.Value)),
|
||||
}
|
||||
|
||||
err := binary.Write(buf, binary.LittleEndian, &info)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = buf.Write([]byte(ea.Name))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = buf.WriteByte(0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = buf.Write(ea.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = buf.Write([]byte{0, 0, 0}[0 : withPadding-entrySize])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// EncodeExtendedAttributes encodes a list of EAs into a FILE_FULL_EA_INFORMATION
|
||||
// buffer for use with BackupWrite, ZwSetEaFile, etc.
|
||||
func EncodeExtendedAttributes(eas []ExtendedAttribute) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
for i := range eas {
|
||||
last := false
|
||||
if i == len(eas)-1 {
|
||||
last = true
|
||||
}
|
||||
|
||||
err := writeEa(&buf, &eas[i], last)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
18
vendor/github.com/Microsoft/go-winio/file.go
generated
vendored
18
vendor/github.com/Microsoft/go-winio/file.go
generated
vendored
@@ -16,6 +16,7 @@ import (
|
||||
//sys createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) = CreateIoCompletionPort
|
||||
//sys getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) = GetQueuedCompletionStatus
|
||||
//sys setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) = SetFileCompletionNotificationModes
|
||||
//sys wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) = ws2_32.WSAGetOverlappedResult
|
||||
|
||||
type atomicBool int32
|
||||
|
||||
@@ -79,6 +80,7 @@ type win32File struct {
|
||||
wg sync.WaitGroup
|
||||
wgLock sync.RWMutex
|
||||
closing atomicBool
|
||||
socket bool
|
||||
readDeadline deadlineHandler
|
||||
writeDeadline deadlineHandler
|
||||
}
|
||||
@@ -109,7 +111,13 @@ func makeWin32File(h syscall.Handle) (*win32File, error) {
|
||||
}
|
||||
|
||||
func MakeOpenFile(h syscall.Handle) (io.ReadWriteCloser, error) {
|
||||
return makeWin32File(h)
|
||||
// If we return the result of makeWin32File directly, it can result in an
|
||||
// interface-wrapped nil, rather than a nil interface value.
|
||||
f, err := makeWin32File(h)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
|
||||
// closeHandle closes the resources associated with a Win32 handle
|
||||
@@ -190,6 +198,10 @@ func (f *win32File) asyncIo(c *ioOperation, d *deadlineHandler, bytes uint32, er
|
||||
if f.closing.isSet() {
|
||||
err = ErrFileClosed
|
||||
}
|
||||
} else if err != nil && f.socket {
|
||||
// err is from Win32. Query the overlapped structure to get the winsock error.
|
||||
var bytes, flags uint32
|
||||
err = wsaGetOverlappedResult(f.handle, &c.o, &bytes, false, &flags)
|
||||
}
|
||||
case <-timeout:
|
||||
cancelIoEx(f.handle, &c.o)
|
||||
@@ -265,6 +277,10 @@ func (f *win32File) Flush() error {
|
||||
return syscall.FlushFileBuffers(f.handle)
|
||||
}
|
||||
|
||||
func (f *win32File) Fd() uintptr {
|
||||
return uintptr(f.handle)
|
||||
}
|
||||
|
||||
func (d *deadlineHandler) set(deadline time.Time) error {
|
||||
d.setLock.Lock()
|
||||
defer d.setLock.Unlock()
|
||||
|
||||
3
vendor/github.com/Microsoft/go-winio/fileinfo.go
generated
vendored
3
vendor/github.com/Microsoft/go-winio/fileinfo.go
generated
vendored
@@ -20,7 +20,8 @@ const (
|
||||
// FileBasicInfo contains file access time and file attributes information.
|
||||
type FileBasicInfo struct {
|
||||
CreationTime, LastAccessTime, LastWriteTime, ChangeTime syscall.Filetime
|
||||
FileAttributes uintptr // includes padding
|
||||
FileAttributes uint32
|
||||
pad uint32 // padding
|
||||
}
|
||||
|
||||
// GetFileBasicInfo retrieves times and attributes for a file.
|
||||
|
||||
9
vendor/github.com/Microsoft/go-winio/go.mod
generated
vendored
Normal file
9
vendor/github.com/Microsoft/go-winio/go.mod
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
module github.com/Microsoft/go-winio
|
||||
|
||||
go 1.12
|
||||
|
||||
require (
|
||||
github.com/pkg/errors v0.8.1
|
||||
github.com/sirupsen/logrus v1.4.1
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b
|
||||
)
|
||||
16
vendor/github.com/Microsoft/go-winio/go.sum
generated
vendored
Normal file
16
vendor/github.com/Microsoft/go-winio/go.sum
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
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/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
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/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b h1:ag/x1USPSsqHud38I9BAC88qdNLDHHtQ4mlgQIZPPNA=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
305
vendor/github.com/Microsoft/go-winio/hvsock.go
generated
vendored
Normal file
305
vendor/github.com/Microsoft/go-winio/hvsock.go
generated
vendored
Normal file
@@ -0,0 +1,305 @@
|
||||
package winio
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/Microsoft/go-winio/pkg/guid"
|
||||
)
|
||||
|
||||
//sys bind(s syscall.Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socketError] = ws2_32.bind
|
||||
|
||||
const (
|
||||
afHvSock = 34 // AF_HYPERV
|
||||
|
||||
socketError = ^uintptr(0)
|
||||
)
|
||||
|
||||
// An HvsockAddr is an address for a AF_HYPERV socket.
|
||||
type HvsockAddr struct {
|
||||
VMID guid.GUID
|
||||
ServiceID guid.GUID
|
||||
}
|
||||
|
||||
type rawHvsockAddr struct {
|
||||
Family uint16
|
||||
_ uint16
|
||||
VMID guid.GUID
|
||||
ServiceID guid.GUID
|
||||
}
|
||||
|
||||
// Network returns the address's network name, "hvsock".
|
||||
func (addr *HvsockAddr) Network() string {
|
||||
return "hvsock"
|
||||
}
|
||||
|
||||
func (addr *HvsockAddr) String() string {
|
||||
return fmt.Sprintf("%s:%s", &addr.VMID, &addr.ServiceID)
|
||||
}
|
||||
|
||||
// VsockServiceID returns an hvsock service ID corresponding to the specified AF_VSOCK port.
|
||||
func VsockServiceID(port uint32) guid.GUID {
|
||||
g, _ := guid.FromString("00000000-facb-11e6-bd58-64006a7986d3")
|
||||
g.Data1 = port
|
||||
return g
|
||||
}
|
||||
|
||||
func (addr *HvsockAddr) raw() rawHvsockAddr {
|
||||
return rawHvsockAddr{
|
||||
Family: afHvSock,
|
||||
VMID: addr.VMID,
|
||||
ServiceID: addr.ServiceID,
|
||||
}
|
||||
}
|
||||
|
||||
func (addr *HvsockAddr) fromRaw(raw *rawHvsockAddr) {
|
||||
addr.VMID = raw.VMID
|
||||
addr.ServiceID = raw.ServiceID
|
||||
}
|
||||
|
||||
// HvsockListener is a socket listener for the AF_HYPERV address family.
|
||||
type HvsockListener struct {
|
||||
sock *win32File
|
||||
addr HvsockAddr
|
||||
}
|
||||
|
||||
// HvsockConn is a connected socket of the AF_HYPERV address family.
|
||||
type HvsockConn struct {
|
||||
sock *win32File
|
||||
local, remote HvsockAddr
|
||||
}
|
||||
|
||||
func newHvSocket() (*win32File, error) {
|
||||
fd, err := syscall.Socket(afHvSock, syscall.SOCK_STREAM, 1)
|
||||
if err != nil {
|
||||
return nil, os.NewSyscallError("socket", err)
|
||||
}
|
||||
f, err := makeWin32File(fd)
|
||||
if err != nil {
|
||||
syscall.Close(fd)
|
||||
return nil, err
|
||||
}
|
||||
f.socket = true
|
||||
return f, nil
|
||||
}
|
||||
|
||||
// ListenHvsock listens for connections on the specified hvsock address.
|
||||
func ListenHvsock(addr *HvsockAddr) (_ *HvsockListener, err error) {
|
||||
l := &HvsockListener{addr: *addr}
|
||||
sock, err := newHvSocket()
|
||||
if err != nil {
|
||||
return nil, l.opErr("listen", err)
|
||||
}
|
||||
sa := addr.raw()
|
||||
err = bind(sock.handle, unsafe.Pointer(&sa), int32(unsafe.Sizeof(sa)))
|
||||
if err != nil {
|
||||
return nil, l.opErr("listen", os.NewSyscallError("socket", err))
|
||||
}
|
||||
err = syscall.Listen(sock.handle, 16)
|
||||
if err != nil {
|
||||
return nil, l.opErr("listen", os.NewSyscallError("listen", err))
|
||||
}
|
||||
return &HvsockListener{sock: sock, addr: *addr}, nil
|
||||
}
|
||||
|
||||
func (l *HvsockListener) opErr(op string, err error) error {
|
||||
return &net.OpError{Op: op, Net: "hvsock", Addr: &l.addr, Err: err}
|
||||
}
|
||||
|
||||
// Addr returns the listener's network address.
|
||||
func (l *HvsockListener) Addr() net.Addr {
|
||||
return &l.addr
|
||||
}
|
||||
|
||||
// Accept waits for the next connection and returns it.
|
||||
func (l *HvsockListener) Accept() (_ net.Conn, err error) {
|
||||
sock, err := newHvSocket()
|
||||
if err != nil {
|
||||
return nil, l.opErr("accept", err)
|
||||
}
|
||||
defer func() {
|
||||
if sock != nil {
|
||||
sock.Close()
|
||||
}
|
||||
}()
|
||||
c, err := l.sock.prepareIo()
|
||||
if err != nil {
|
||||
return nil, l.opErr("accept", err)
|
||||
}
|
||||
defer l.sock.wg.Done()
|
||||
|
||||
// AcceptEx, per documentation, requires an extra 16 bytes per address.
|
||||
const addrlen = uint32(16 + unsafe.Sizeof(rawHvsockAddr{}))
|
||||
var addrbuf [addrlen * 2]byte
|
||||
|
||||
var bytes uint32
|
||||
err = syscall.AcceptEx(l.sock.handle, sock.handle, &addrbuf[0], 0, addrlen, addrlen, &bytes, &c.o)
|
||||
_, err = l.sock.asyncIo(c, nil, bytes, err)
|
||||
if err != nil {
|
||||
return nil, l.opErr("accept", os.NewSyscallError("acceptex", err))
|
||||
}
|
||||
conn := &HvsockConn{
|
||||
sock: sock,
|
||||
}
|
||||
conn.local.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[0])))
|
||||
conn.remote.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[addrlen])))
|
||||
sock = nil
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
// Close closes the listener, causing any pending Accept calls to fail.
|
||||
func (l *HvsockListener) Close() error {
|
||||
return l.sock.Close()
|
||||
}
|
||||
|
||||
/* Need to finish ConnectEx handling
|
||||
func DialHvsock(ctx context.Context, addr *HvsockAddr) (*HvsockConn, error) {
|
||||
sock, err := newHvSocket()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
if sock != nil {
|
||||
sock.Close()
|
||||
}
|
||||
}()
|
||||
c, err := sock.prepareIo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer sock.wg.Done()
|
||||
var bytes uint32
|
||||
err = windows.ConnectEx(windows.Handle(sock.handle), sa, nil, 0, &bytes, &c.o)
|
||||
_, err = sock.asyncIo(ctx, c, nil, bytes, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conn := &HvsockConn{
|
||||
sock: sock,
|
||||
remote: *addr,
|
||||
}
|
||||
sock = nil
|
||||
return conn, nil
|
||||
}
|
||||
*/
|
||||
|
||||
func (conn *HvsockConn) opErr(op string, err error) error {
|
||||
return &net.OpError{Op: op, Net: "hvsock", Source: &conn.local, Addr: &conn.remote, Err: err}
|
||||
}
|
||||
|
||||
func (conn *HvsockConn) Read(b []byte) (int, error) {
|
||||
c, err := conn.sock.prepareIo()
|
||||
if err != nil {
|
||||
return 0, conn.opErr("read", err)
|
||||
}
|
||||
defer conn.sock.wg.Done()
|
||||
buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))}
|
||||
var flags, bytes uint32
|
||||
err = syscall.WSARecv(conn.sock.handle, &buf, 1, &bytes, &flags, &c.o, nil)
|
||||
n, err := conn.sock.asyncIo(c, &conn.sock.readDeadline, bytes, err)
|
||||
if err != nil {
|
||||
if _, ok := err.(syscall.Errno); ok {
|
||||
err = os.NewSyscallError("wsarecv", err)
|
||||
}
|
||||
return 0, conn.opErr("read", err)
|
||||
} else if n == 0 {
|
||||
err = io.EOF
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (conn *HvsockConn) Write(b []byte) (int, error) {
|
||||
t := 0
|
||||
for len(b) != 0 {
|
||||
n, err := conn.write(b)
|
||||
if err != nil {
|
||||
return t + n, err
|
||||
}
|
||||
t += n
|
||||
b = b[n:]
|
||||
}
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func (conn *HvsockConn) write(b []byte) (int, error) {
|
||||
c, err := conn.sock.prepareIo()
|
||||
if err != nil {
|
||||
return 0, conn.opErr("write", err)
|
||||
}
|
||||
defer conn.sock.wg.Done()
|
||||
buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))}
|
||||
var bytes uint32
|
||||
err = syscall.WSASend(conn.sock.handle, &buf, 1, &bytes, 0, &c.o, nil)
|
||||
n, err := conn.sock.asyncIo(c, &conn.sock.writeDeadline, bytes, err)
|
||||
if err != nil {
|
||||
if _, ok := err.(syscall.Errno); ok {
|
||||
err = os.NewSyscallError("wsasend", err)
|
||||
}
|
||||
return 0, conn.opErr("write", err)
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Close closes the socket connection, failing any pending read or write calls.
|
||||
func (conn *HvsockConn) Close() error {
|
||||
return conn.sock.Close()
|
||||
}
|
||||
|
||||
func (conn *HvsockConn) shutdown(how int) error {
|
||||
err := syscall.Shutdown(conn.sock.handle, syscall.SHUT_RD)
|
||||
if err != nil {
|
||||
return os.NewSyscallError("shutdown", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CloseRead shuts down the read end of the socket.
|
||||
func (conn *HvsockConn) CloseRead() error {
|
||||
err := conn.shutdown(syscall.SHUT_RD)
|
||||
if err != nil {
|
||||
return conn.opErr("close", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CloseWrite shuts down the write end of the socket, notifying the other endpoint that
|
||||
// no more data will be written.
|
||||
func (conn *HvsockConn) CloseWrite() error {
|
||||
err := conn.shutdown(syscall.SHUT_WR)
|
||||
if err != nil {
|
||||
return conn.opErr("close", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// LocalAddr returns the local address of the connection.
|
||||
func (conn *HvsockConn) LocalAddr() net.Addr {
|
||||
return &conn.local
|
||||
}
|
||||
|
||||
// RemoteAddr returns the remote address of the connection.
|
||||
func (conn *HvsockConn) RemoteAddr() net.Addr {
|
||||
return &conn.remote
|
||||
}
|
||||
|
||||
// SetDeadline implements the net.Conn SetDeadline method.
|
||||
func (conn *HvsockConn) SetDeadline(t time.Time) error {
|
||||
conn.SetReadDeadline(t)
|
||||
conn.SetWriteDeadline(t)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetReadDeadline implements the net.Conn SetReadDeadline method.
|
||||
func (conn *HvsockConn) SetReadDeadline(t time.Time) error {
|
||||
return conn.sock.SetReadDeadline(t)
|
||||
}
|
||||
|
||||
// SetWriteDeadline implements the net.Conn SetWriteDeadline method.
|
||||
func (conn *HvsockConn) SetWriteDeadline(t time.Time) error {
|
||||
return conn.sock.SetWriteDeadline(t)
|
||||
}
|
||||
266
vendor/github.com/Microsoft/go-winio/pipe.go
generated
vendored
266
vendor/github.com/Microsoft/go-winio/pipe.go
generated
vendored
@@ -3,10 +3,13 @@
|
||||
package winio
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
@@ -15,10 +18,51 @@ import (
|
||||
//sys connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) = ConnectNamedPipe
|
||||
//sys createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateNamedPipeW
|
||||
//sys createFile(name string, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateFileW
|
||||
//sys waitNamedPipe(name string, timeout uint32) (err error) = WaitNamedPipeW
|
||||
//sys getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) = GetNamedPipeInfo
|
||||
//sys getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) = GetNamedPipeHandleStateW
|
||||
//sys localAlloc(uFlags uint32, length uint32) (ptr uintptr) = LocalAlloc
|
||||
//sys ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntstatus) = ntdll.NtCreateNamedPipeFile
|
||||
//sys rtlNtStatusToDosError(status ntstatus) (winerr error) = ntdll.RtlNtStatusToDosErrorNoTeb
|
||||
//sys rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntstatus) = ntdll.RtlDosPathNameToNtPathName_U
|
||||
//sys rtlDefaultNpAcl(dacl *uintptr) (status ntstatus) = ntdll.RtlDefaultNpAcl
|
||||
|
||||
type ioStatusBlock struct {
|
||||
Status, Information uintptr
|
||||
}
|
||||
|
||||
type objectAttributes struct {
|
||||
Length uintptr
|
||||
RootDirectory uintptr
|
||||
ObjectName *unicodeString
|
||||
Attributes uintptr
|
||||
SecurityDescriptor *securityDescriptor
|
||||
SecurityQoS uintptr
|
||||
}
|
||||
|
||||
type unicodeString struct {
|
||||
Length uint16
|
||||
MaximumLength uint16
|
||||
Buffer uintptr
|
||||
}
|
||||
|
||||
type securityDescriptor struct {
|
||||
Revision byte
|
||||
Sbz1 byte
|
||||
Control uint16
|
||||
Owner uintptr
|
||||
Group uintptr
|
||||
Sacl uintptr
|
||||
Dacl uintptr
|
||||
}
|
||||
|
||||
type ntstatus int32
|
||||
|
||||
func (status ntstatus) Err() error {
|
||||
if status >= 0 {
|
||||
return nil
|
||||
}
|
||||
return rtlNtStatusToDosError(status)
|
||||
}
|
||||
|
||||
const (
|
||||
cERROR_PIPE_BUSY = syscall.Errno(231)
|
||||
@@ -26,21 +70,20 @@ const (
|
||||
cERROR_PIPE_CONNECTED = syscall.Errno(535)
|
||||
cERROR_SEM_TIMEOUT = syscall.Errno(121)
|
||||
|
||||
cPIPE_ACCESS_DUPLEX = 0x3
|
||||
cFILE_FLAG_FIRST_PIPE_INSTANCE = 0x80000
|
||||
cSECURITY_SQOS_PRESENT = 0x100000
|
||||
cSECURITY_ANONYMOUS = 0
|
||||
|
||||
cPIPE_REJECT_REMOTE_CLIENTS = 0x8
|
||||
|
||||
cPIPE_UNLIMITED_INSTANCES = 255
|
||||
|
||||
cNMPWAIT_USE_DEFAULT_WAIT = 0
|
||||
cNMPWAIT_NOWAIT = 1
|
||||
cSECURITY_SQOS_PRESENT = 0x100000
|
||||
cSECURITY_ANONYMOUS = 0
|
||||
|
||||
cPIPE_TYPE_MESSAGE = 4
|
||||
|
||||
cPIPE_READMODE_MESSAGE = 2
|
||||
|
||||
cFILE_OPEN = 1
|
||||
cFILE_CREATE = 2
|
||||
|
||||
cFILE_PIPE_MESSAGE_TYPE = 1
|
||||
cFILE_PIPE_REJECT_REMOTE_CLIENTS = 2
|
||||
|
||||
cSE_DACL_PRESENT = 4
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -121,6 +164,11 @@ func (f *win32MessageBytePipe) Read(b []byte) (int, error) {
|
||||
// zero-byte message, ensure that all future Read() calls
|
||||
// also return EOF.
|
||||
f.readEOF = true
|
||||
} else if err == syscall.ERROR_MORE_DATA {
|
||||
// ERROR_MORE_DATA indicates that the pipe's read mode is message mode
|
||||
// and the message still has more bytes. Treat this as a success, since
|
||||
// this package presents all named pipes as byte streams.
|
||||
err = nil
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
@@ -133,40 +181,53 @@ func (s pipeAddress) String() string {
|
||||
return string(s)
|
||||
}
|
||||
|
||||
// tryDialPipe attempts to dial the pipe at `path` until `ctx` cancellation or timeout.
|
||||
func tryDialPipe(ctx context.Context, path *string) (syscall.Handle, error) {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return syscall.Handle(0), ctx.Err()
|
||||
default:
|
||||
h, err := createFile(*path, syscall.GENERIC_READ|syscall.GENERIC_WRITE, 0, nil, syscall.OPEN_EXISTING, syscall.FILE_FLAG_OVERLAPPED|cSECURITY_SQOS_PRESENT|cSECURITY_ANONYMOUS, 0)
|
||||
if err == nil {
|
||||
return h, nil
|
||||
}
|
||||
if err != cERROR_PIPE_BUSY {
|
||||
return h, &os.PathError{Err: err, Op: "open", Path: *path}
|
||||
}
|
||||
// Wait 10 msec and try again. This is a rather simplistic
|
||||
// view, as we always try each 10 milliseconds.
|
||||
time.Sleep(time.Millisecond * 10)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DialPipe connects to a named pipe by path, timing out if the connection
|
||||
// takes longer than the specified duration. If timeout is nil, then the timeout
|
||||
// is the default timeout established by the pipe server.
|
||||
// takes longer than the specified duration. If timeout is nil, then we use
|
||||
// a default timeout of 2 seconds. (We do not use WaitNamedPipe.)
|
||||
func DialPipe(path string, timeout *time.Duration) (net.Conn, error) {
|
||||
var absTimeout time.Time
|
||||
if timeout != nil {
|
||||
absTimeout = time.Now().Add(*timeout)
|
||||
} else {
|
||||
absTimeout = time.Now().Add(time.Second * 2)
|
||||
}
|
||||
ctx, _ := context.WithDeadline(context.Background(), absTimeout)
|
||||
conn, err := DialPipeContext(ctx, path)
|
||||
if err == context.DeadlineExceeded {
|
||||
return nil, ErrTimeout
|
||||
}
|
||||
return conn, err
|
||||
}
|
||||
|
||||
// DialPipeContext attempts to connect to a named pipe by `path` until `ctx`
|
||||
// cancellation or timeout.
|
||||
func DialPipeContext(ctx context.Context, path string) (net.Conn, error) {
|
||||
var err error
|
||||
var h syscall.Handle
|
||||
for {
|
||||
h, err = createFile(path, syscall.GENERIC_READ|syscall.GENERIC_WRITE, 0, nil, syscall.OPEN_EXISTING, syscall.FILE_FLAG_OVERLAPPED|cSECURITY_SQOS_PRESENT|cSECURITY_ANONYMOUS, 0)
|
||||
if err != cERROR_PIPE_BUSY {
|
||||
break
|
||||
}
|
||||
now := time.Now()
|
||||
var ms uint32
|
||||
if absTimeout.IsZero() {
|
||||
ms = cNMPWAIT_USE_DEFAULT_WAIT
|
||||
} else if now.After(absTimeout) {
|
||||
ms = cNMPWAIT_NOWAIT
|
||||
} else {
|
||||
ms = uint32(absTimeout.Sub(now).Nanoseconds() / 1000 / 1000)
|
||||
}
|
||||
err = waitNamedPipe(path, ms)
|
||||
if err != nil {
|
||||
if err == cERROR_SEM_TIMEOUT {
|
||||
return nil, ErrTimeout
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
h, err = tryDialPipe(ctx, &path)
|
||||
if err != nil {
|
||||
return nil, &os.PathError{Op: "open", Path: path, Err: err}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var flags uint32
|
||||
@@ -175,16 +236,6 @@ func DialPipe(path string, timeout *time.Duration) (net.Conn, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var state uint32
|
||||
err = getNamedPipeHandleState(h, &state, nil, nil, nil, nil, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if state&cPIPE_READMODE_MESSAGE != 0 {
|
||||
return nil, &os.PathError{Op: "open", Path: path, Err: errors.New("message readmode pipes not supported")}
|
||||
}
|
||||
|
||||
f, err := makeWin32File(h)
|
||||
if err != nil {
|
||||
syscall.Close(h)
|
||||
@@ -207,43 +258,87 @@ type acceptResponse struct {
|
||||
}
|
||||
|
||||
type win32PipeListener struct {
|
||||
firstHandle syscall.Handle
|
||||
path string
|
||||
securityDescriptor []byte
|
||||
config PipeConfig
|
||||
acceptCh chan (chan acceptResponse)
|
||||
closeCh chan int
|
||||
doneCh chan int
|
||||
firstHandle syscall.Handle
|
||||
path string
|
||||
config PipeConfig
|
||||
acceptCh chan (chan acceptResponse)
|
||||
closeCh chan int
|
||||
doneCh chan int
|
||||
}
|
||||
|
||||
func makeServerPipeHandle(path string, securityDescriptor []byte, c *PipeConfig, first bool) (syscall.Handle, error) {
|
||||
var flags uint32 = cPIPE_ACCESS_DUPLEX | syscall.FILE_FLAG_OVERLAPPED
|
||||
if first {
|
||||
flags |= cFILE_FLAG_FIRST_PIPE_INSTANCE
|
||||
}
|
||||
|
||||
var mode uint32 = cPIPE_REJECT_REMOTE_CLIENTS
|
||||
if c.MessageMode {
|
||||
mode |= cPIPE_TYPE_MESSAGE
|
||||
}
|
||||
|
||||
sa := &syscall.SecurityAttributes{}
|
||||
sa.Length = uint32(unsafe.Sizeof(*sa))
|
||||
if securityDescriptor != nil {
|
||||
len := uint32(len(securityDescriptor))
|
||||
sa.SecurityDescriptor = localAlloc(0, len)
|
||||
defer localFree(sa.SecurityDescriptor)
|
||||
copy((*[0xffff]byte)(unsafe.Pointer(sa.SecurityDescriptor))[:], securityDescriptor)
|
||||
}
|
||||
h, err := createNamedPipe(path, flags, mode, cPIPE_UNLIMITED_INSTANCES, uint32(c.OutputBufferSize), uint32(c.InputBufferSize), 0, sa)
|
||||
func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (syscall.Handle, error) {
|
||||
path16, err := syscall.UTF16FromString(path)
|
||||
if err != nil {
|
||||
return 0, &os.PathError{Op: "open", Path: path, Err: err}
|
||||
}
|
||||
|
||||
var oa objectAttributes
|
||||
oa.Length = unsafe.Sizeof(oa)
|
||||
|
||||
var ntPath unicodeString
|
||||
if err := rtlDosPathNameToNtPathName(&path16[0], &ntPath, 0, 0).Err(); err != nil {
|
||||
return 0, &os.PathError{Op: "open", Path: path, Err: err}
|
||||
}
|
||||
defer localFree(ntPath.Buffer)
|
||||
oa.ObjectName = &ntPath
|
||||
|
||||
// The security descriptor is only needed for the first pipe.
|
||||
if first {
|
||||
if sd != nil {
|
||||
len := uint32(len(sd))
|
||||
sdb := localAlloc(0, len)
|
||||
defer localFree(sdb)
|
||||
copy((*[0xffff]byte)(unsafe.Pointer(sdb))[:], sd)
|
||||
oa.SecurityDescriptor = (*securityDescriptor)(unsafe.Pointer(sdb))
|
||||
} else {
|
||||
// Construct the default named pipe security descriptor.
|
||||
var dacl uintptr
|
||||
if err := rtlDefaultNpAcl(&dacl).Err(); err != nil {
|
||||
return 0, fmt.Errorf("getting default named pipe ACL: %s", err)
|
||||
}
|
||||
defer localFree(dacl)
|
||||
|
||||
sdb := &securityDescriptor{
|
||||
Revision: 1,
|
||||
Control: cSE_DACL_PRESENT,
|
||||
Dacl: dacl,
|
||||
}
|
||||
oa.SecurityDescriptor = sdb
|
||||
}
|
||||
}
|
||||
|
||||
typ := uint32(cFILE_PIPE_REJECT_REMOTE_CLIENTS)
|
||||
if c.MessageMode {
|
||||
typ |= cFILE_PIPE_MESSAGE_TYPE
|
||||
}
|
||||
|
||||
disposition := uint32(cFILE_OPEN)
|
||||
access := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE | syscall.SYNCHRONIZE)
|
||||
if first {
|
||||
disposition = cFILE_CREATE
|
||||
// By not asking for read or write access, the named pipe file system
|
||||
// will put this pipe into an initially disconnected state, blocking
|
||||
// client connections until the next call with first == false.
|
||||
access = syscall.SYNCHRONIZE
|
||||
}
|
||||
|
||||
timeout := int64(-50 * 10000) // 50ms
|
||||
|
||||
var (
|
||||
h syscall.Handle
|
||||
iosb ioStatusBlock
|
||||
)
|
||||
err = ntCreateNamedPipeFile(&h, access, &oa, &iosb, syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE, disposition, 0, typ, 0, 0, 0xffffffff, uint32(c.InputBufferSize), uint32(c.OutputBufferSize), &timeout).Err()
|
||||
if err != nil {
|
||||
return 0, &os.PathError{Op: "open", Path: path, Err: err}
|
||||
}
|
||||
|
||||
runtime.KeepAlive(ntPath)
|
||||
return h, nil
|
||||
}
|
||||
|
||||
func (l *win32PipeListener) makeServerPipe() (*win32File, error) {
|
||||
h, err := makeServerPipeHandle(l.path, l.securityDescriptor, &l.config, false)
|
||||
h, err := makeServerPipeHandle(l.path, nil, &l.config, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -354,22 +449,13 @@ func ListenPipe(path string, c *PipeConfig) (net.Listener, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Immediately open and then close a client handle so that the named pipe is
|
||||
// created but not currently accepting connections.
|
||||
h2, err := createFile(path, 0, 0, nil, syscall.OPEN_EXISTING, cSECURITY_SQOS_PRESENT|cSECURITY_ANONYMOUS, 0)
|
||||
if err != nil {
|
||||
syscall.Close(h)
|
||||
return nil, err
|
||||
}
|
||||
syscall.Close(h2)
|
||||
l := &win32PipeListener{
|
||||
firstHandle: h,
|
||||
path: path,
|
||||
securityDescriptor: sd,
|
||||
config: *c,
|
||||
acceptCh: make(chan (chan acceptResponse)),
|
||||
closeCh: make(chan int),
|
||||
doneCh: make(chan int),
|
||||
firstHandle: h,
|
||||
path: path,
|
||||
config: *c,
|
||||
acceptCh: make(chan (chan acceptResponse)),
|
||||
closeCh: make(chan int),
|
||||
doneCh: make(chan int),
|
||||
}
|
||||
go l.listenerRoutine()
|
||||
return l, nil
|
||||
|
||||
235
vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go
generated
vendored
Normal file
235
vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go
generated
vendored
Normal file
@@ -0,0 +1,235 @@
|
||||
// Package guid provides a GUID type. The backing structure for a GUID is
|
||||
// identical to that used by the golang.org/x/sys/windows GUID type.
|
||||
// There are two main binary encodings used for a GUID, the big-endian encoding,
|
||||
// and the Windows (mixed-endian) encoding. See here for details:
|
||||
// https://en.wikipedia.org/wiki/Universally_unique_identifier#Encoding
|
||||
package guid
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/sha1"
|
||||
"encoding"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
// Variant specifies which GUID variant (or "type") of the GUID. It determines
|
||||
// how the entirety of the rest of the GUID is interpreted.
|
||||
type Variant uint8
|
||||
|
||||
// The variants specified by RFC 4122.
|
||||
const (
|
||||
// VariantUnknown specifies a GUID variant which does not conform to one of
|
||||
// the variant encodings specified in RFC 4122.
|
||||
VariantUnknown Variant = iota
|
||||
VariantNCS
|
||||
VariantRFC4122
|
||||
VariantMicrosoft
|
||||
VariantFuture
|
||||
)
|
||||
|
||||
// Version specifies how the bits in the GUID were generated. For instance, a
|
||||
// version 4 GUID is randomly generated, and a version 5 is generated from the
|
||||
// hash of an input string.
|
||||
type Version uint8
|
||||
|
||||
var _ = (encoding.TextMarshaler)(GUID{})
|
||||
var _ = (encoding.TextUnmarshaler)(&GUID{})
|
||||
|
||||
// GUID represents a GUID/UUID. It has the same structure as
|
||||
// golang.org/x/sys/windows.GUID so that it can be used with functions expecting
|
||||
// that type. It is defined as its own type so that stringification and
|
||||
// marshaling can be supported. The representation matches that used by native
|
||||
// Windows code.
|
||||
type GUID windows.GUID
|
||||
|
||||
// NewV4 returns a new version 4 (pseudorandom) GUID, as defined by RFC 4122.
|
||||
func NewV4() (GUID, error) {
|
||||
var b [16]byte
|
||||
if _, err := rand.Read(b[:]); err != nil {
|
||||
return GUID{}, err
|
||||
}
|
||||
|
||||
g := FromArray(b)
|
||||
g.setVersion(4) // Version 4 means randomly generated.
|
||||
g.setVariant(VariantRFC4122)
|
||||
|
||||
return g, nil
|
||||
}
|
||||
|
||||
// NewV5 returns a new version 5 (generated from a string via SHA-1 hashing)
|
||||
// GUID, as defined by RFC 4122. The RFC is unclear on the encoding of the name,
|
||||
// and the sample code treats it as a series of bytes, so we do the same here.
|
||||
//
|
||||
// Some implementations, such as those found on Windows, treat the name as a
|
||||
// big-endian UTF16 stream of bytes. If that is desired, the string can be
|
||||
// encoded as such before being passed to this function.
|
||||
func NewV5(namespace GUID, name []byte) (GUID, error) {
|
||||
b := sha1.New()
|
||||
namespaceBytes := namespace.ToArray()
|
||||
b.Write(namespaceBytes[:])
|
||||
b.Write(name)
|
||||
|
||||
a := [16]byte{}
|
||||
copy(a[:], b.Sum(nil))
|
||||
|
||||
g := FromArray(a)
|
||||
g.setVersion(5) // Version 5 means generated from a string.
|
||||
g.setVariant(VariantRFC4122)
|
||||
|
||||
return g, nil
|
||||
}
|
||||
|
||||
func fromArray(b [16]byte, order binary.ByteOrder) GUID {
|
||||
var g GUID
|
||||
g.Data1 = order.Uint32(b[0:4])
|
||||
g.Data2 = order.Uint16(b[4:6])
|
||||
g.Data3 = order.Uint16(b[6:8])
|
||||
copy(g.Data4[:], b[8:16])
|
||||
return g
|
||||
}
|
||||
|
||||
func (g GUID) toArray(order binary.ByteOrder) [16]byte {
|
||||
b := [16]byte{}
|
||||
order.PutUint32(b[0:4], g.Data1)
|
||||
order.PutUint16(b[4:6], g.Data2)
|
||||
order.PutUint16(b[6:8], g.Data3)
|
||||
copy(b[8:16], g.Data4[:])
|
||||
return b
|
||||
}
|
||||
|
||||
// FromArray constructs a GUID from a big-endian encoding array of 16 bytes.
|
||||
func FromArray(b [16]byte) GUID {
|
||||
return fromArray(b, binary.BigEndian)
|
||||
}
|
||||
|
||||
// ToArray returns an array of 16 bytes representing the GUID in big-endian
|
||||
// encoding.
|
||||
func (g GUID) ToArray() [16]byte {
|
||||
return g.toArray(binary.BigEndian)
|
||||
}
|
||||
|
||||
// FromWindowsArray constructs a GUID from a Windows encoding array of bytes.
|
||||
func FromWindowsArray(b [16]byte) GUID {
|
||||
return fromArray(b, binary.LittleEndian)
|
||||
}
|
||||
|
||||
// ToWindowsArray returns an array of 16 bytes representing the GUID in Windows
|
||||
// encoding.
|
||||
func (g GUID) ToWindowsArray() [16]byte {
|
||||
return g.toArray(binary.LittleEndian)
|
||||
}
|
||||
|
||||
func (g GUID) String() string {
|
||||
return fmt.Sprintf(
|
||||
"%08x-%04x-%04x-%04x-%012x",
|
||||
g.Data1,
|
||||
g.Data2,
|
||||
g.Data3,
|
||||
g.Data4[:2],
|
||||
g.Data4[2:])
|
||||
}
|
||||
|
||||
// FromString parses a string containing a GUID and returns the GUID. The only
|
||||
// format currently supported is the `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
|
||||
// format.
|
||||
func FromString(s string) (GUID, error) {
|
||||
if len(s) != 36 {
|
||||
return GUID{}, fmt.Errorf("invalid GUID %q", s)
|
||||
}
|
||||
if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
|
||||
return GUID{}, fmt.Errorf("invalid GUID %q", s)
|
||||
}
|
||||
|
||||
var g GUID
|
||||
|
||||
data1, err := strconv.ParseUint(s[0:8], 16, 32)
|
||||
if err != nil {
|
||||
return GUID{}, fmt.Errorf("invalid GUID %q", s)
|
||||
}
|
||||
g.Data1 = uint32(data1)
|
||||
|
||||
data2, err := strconv.ParseUint(s[9:13], 16, 16)
|
||||
if err != nil {
|
||||
return GUID{}, fmt.Errorf("invalid GUID %q", s)
|
||||
}
|
||||
g.Data2 = uint16(data2)
|
||||
|
||||
data3, err := strconv.ParseUint(s[14:18], 16, 16)
|
||||
if err != nil {
|
||||
return GUID{}, fmt.Errorf("invalid GUID %q", s)
|
||||
}
|
||||
g.Data3 = uint16(data3)
|
||||
|
||||
for i, x := range []int{19, 21, 24, 26, 28, 30, 32, 34} {
|
||||
v, err := strconv.ParseUint(s[x:x+2], 16, 8)
|
||||
if err != nil {
|
||||
return GUID{}, fmt.Errorf("invalid GUID %q", s)
|
||||
}
|
||||
g.Data4[i] = uint8(v)
|
||||
}
|
||||
|
||||
return g, nil
|
||||
}
|
||||
|
||||
func (g *GUID) setVariant(v Variant) {
|
||||
d := g.Data4[0]
|
||||
switch v {
|
||||
case VariantNCS:
|
||||
d = (d & 0x7f)
|
||||
case VariantRFC4122:
|
||||
d = (d & 0x3f) | 0x80
|
||||
case VariantMicrosoft:
|
||||
d = (d & 0x1f) | 0xc0
|
||||
case VariantFuture:
|
||||
d = (d & 0x0f) | 0xe0
|
||||
case VariantUnknown:
|
||||
fallthrough
|
||||
default:
|
||||
panic(fmt.Sprintf("invalid variant: %d", v))
|
||||
}
|
||||
g.Data4[0] = d
|
||||
}
|
||||
|
||||
// Variant returns the GUID variant, as defined in RFC 4122.
|
||||
func (g GUID) Variant() Variant {
|
||||
b := g.Data4[0]
|
||||
if b&0x80 == 0 {
|
||||
return VariantNCS
|
||||
} else if b&0xc0 == 0x80 {
|
||||
return VariantRFC4122
|
||||
} else if b&0xe0 == 0xc0 {
|
||||
return VariantMicrosoft
|
||||
} else if b&0xe0 == 0xe0 {
|
||||
return VariantFuture
|
||||
}
|
||||
return VariantUnknown
|
||||
}
|
||||
|
||||
func (g *GUID) setVersion(v Version) {
|
||||
g.Data3 = (g.Data3 & 0x0fff) | (uint16(v) << 12)
|
||||
}
|
||||
|
||||
// Version returns the GUID version, as defined in RFC 4122.
|
||||
func (g GUID) Version() Version {
|
||||
return Version((g.Data3 & 0xF000) >> 12)
|
||||
}
|
||||
|
||||
// MarshalText returns the textual representation of the GUID.
|
||||
func (g GUID) MarshalText() ([]byte, error) {
|
||||
return []byte(g.String()), nil
|
||||
}
|
||||
|
||||
// UnmarshalText takes the textual representation of a GUID, and unmarhals it
|
||||
// into this GUID.
|
||||
func (g *GUID) UnmarshalText(text []byte) error {
|
||||
g2, err := FromString(string(text))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*g = g2
|
||||
return nil
|
||||
}
|
||||
2
vendor/github.com/Microsoft/go-winio/syscall.go
generated
vendored
2
vendor/github.com/Microsoft/go-winio/syscall.go
generated
vendored
@@ -1,3 +1,3 @@
|
||||
package winio
|
||||
|
||||
//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go file.go pipe.go sd.go fileinfo.go privilege.go backup.go
|
||||
//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go file.go pipe.go sd.go fileinfo.go privilege.go backup.go hvsock.go
|
||||
|
||||
88
vendor/github.com/Microsoft/go-winio/zsyscall_windows.go
generated
vendored
88
vendor/github.com/Microsoft/go-winio/zsyscall_windows.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT
|
||||
// Code generated by 'go generate'; DO NOT EDIT.
|
||||
|
||||
package winio
|
||||
|
||||
@@ -38,19 +38,25 @@ func errnoErr(e syscall.Errno) error {
|
||||
|
||||
var (
|
||||
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||
modws2_32 = windows.NewLazySystemDLL("ws2_32.dll")
|
||||
modntdll = windows.NewLazySystemDLL("ntdll.dll")
|
||||
modadvapi32 = windows.NewLazySystemDLL("advapi32.dll")
|
||||
|
||||
procCancelIoEx = modkernel32.NewProc("CancelIoEx")
|
||||
procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort")
|
||||
procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus")
|
||||
procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes")
|
||||
procWSAGetOverlappedResult = modws2_32.NewProc("WSAGetOverlappedResult")
|
||||
procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe")
|
||||
procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW")
|
||||
procCreateFileW = modkernel32.NewProc("CreateFileW")
|
||||
procWaitNamedPipeW = modkernel32.NewProc("WaitNamedPipeW")
|
||||
procGetNamedPipeInfo = modkernel32.NewProc("GetNamedPipeInfo")
|
||||
procGetNamedPipeHandleStateW = modkernel32.NewProc("GetNamedPipeHandleStateW")
|
||||
procLocalAlloc = modkernel32.NewProc("LocalAlloc")
|
||||
procNtCreateNamedPipeFile = modntdll.NewProc("NtCreateNamedPipeFile")
|
||||
procRtlNtStatusToDosErrorNoTeb = modntdll.NewProc("RtlNtStatusToDosErrorNoTeb")
|
||||
procRtlDosPathNameToNtPathName_U = modntdll.NewProc("RtlDosPathNameToNtPathName_U")
|
||||
procRtlDefaultNpAcl = modntdll.NewProc("RtlDefaultNpAcl")
|
||||
procLookupAccountNameW = modadvapi32.NewProc("LookupAccountNameW")
|
||||
procConvertSidToStringSidW = modadvapi32.NewProc("ConvertSidToStringSidW")
|
||||
procConvertStringSecurityDescriptorToSecurityDescriptorW = modadvapi32.NewProc("ConvertStringSecurityDescriptorToSecurityDescriptorW")
|
||||
@@ -69,6 +75,7 @@ var (
|
||||
procLookupPrivilegeDisplayNameW = modadvapi32.NewProc("LookupPrivilegeDisplayNameW")
|
||||
procBackupRead = modkernel32.NewProc("BackupRead")
|
||||
procBackupWrite = modkernel32.NewProc("BackupWrite")
|
||||
procbind = modws2_32.NewProc("bind")
|
||||
)
|
||||
|
||||
func cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) {
|
||||
@@ -120,6 +127,24 @@ func setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err erro
|
||||
return
|
||||
}
|
||||
|
||||
func wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) {
|
||||
var _p0 uint32
|
||||
if wait {
|
||||
_p0 = 1
|
||||
} else {
|
||||
_p0 = 0
|
||||
}
|
||||
r1, _, e1 := syscall.Syscall6(procWSAGetOverlappedResult.Addr(), 5, uintptr(h), uintptr(unsafe.Pointer(o)), uintptr(unsafe.Pointer(bytes)), uintptr(_p0), uintptr(unsafe.Pointer(flags)), 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procConnectNamedPipe.Addr(), 2, uintptr(pipe), uintptr(unsafe.Pointer(o)), 0)
|
||||
if r1 == 0 {
|
||||
@@ -176,27 +201,6 @@ func _createFile(name *uint16, access uint32, mode uint32, sa *syscall.SecurityA
|
||||
return
|
||||
}
|
||||
|
||||
func waitNamedPipe(name string, timeout uint32) (err error) {
|
||||
var _p0 *uint16
|
||||
_p0, err = syscall.UTF16PtrFromString(name)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return _waitNamedPipe(_p0, timeout)
|
||||
}
|
||||
|
||||
func _waitNamedPipe(name *uint16, timeout uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procWaitNamedPipeW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(timeout), 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procGetNamedPipeInfo.Addr(), 5, uintptr(pipe), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(outSize)), uintptr(unsafe.Pointer(inSize)), uintptr(unsafe.Pointer(maxInstances)), 0)
|
||||
if r1 == 0 {
|
||||
@@ -227,6 +231,32 @@ func localAlloc(uFlags uint32, length uint32) (ptr uintptr) {
|
||||
return
|
||||
}
|
||||
|
||||
func ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntstatus) {
|
||||
r0, _, _ := syscall.Syscall15(procNtCreateNamedPipeFile.Addr(), 14, uintptr(unsafe.Pointer(pipe)), uintptr(access), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(share), uintptr(disposition), uintptr(options), uintptr(typ), uintptr(readMode), uintptr(completionMode), uintptr(maxInstances), uintptr(inboundQuota), uintptr(outputQuota), uintptr(unsafe.Pointer(timeout)), 0)
|
||||
status = ntstatus(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func rtlNtStatusToDosError(status ntstatus) (winerr error) {
|
||||
r0, _, _ := syscall.Syscall(procRtlNtStatusToDosErrorNoTeb.Addr(), 1, uintptr(status), 0, 0)
|
||||
if r0 != 0 {
|
||||
winerr = syscall.Errno(r0)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntstatus) {
|
||||
r0, _, _ := syscall.Syscall6(procRtlDosPathNameToNtPathName_U.Addr(), 4, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(ntName)), uintptr(filePart), uintptr(reserved), 0, 0)
|
||||
status = ntstatus(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func rtlDefaultNpAcl(dacl *uintptr) (status ntstatus) {
|
||||
r0, _, _ := syscall.Syscall(procRtlDefaultNpAcl.Addr(), 1, uintptr(unsafe.Pointer(dacl)), 0, 0)
|
||||
status = ntstatus(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) {
|
||||
var _p0 *uint16
|
||||
_p0, err = syscall.UTF16PtrFromString(accountName)
|
||||
@@ -518,3 +548,15 @@ func backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, p
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func bind(s syscall.Handle, name unsafe.Pointer, namelen int32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen))
|
||||
if r1 == socketError {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
7
vendor/github.com/aktau/github-release/.gitignore
generated
vendored
Normal file
7
vendor/github.com/aktau/github-release/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
/github-release
|
||||
/go-app
|
||||
|
||||
*.exe
|
||||
|
||||
/bin
|
||||
/var/cache
|
||||
10
vendor/github.com/aktau/github-release/CONTRIBUTING.md
generated
vendored
Normal file
10
vendor/github.com/aktau/github-release/CONTRIBUTING.md
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
## Releasing new versions
|
||||
|
||||
1) Bump the version in github/version.go
|
||||
|
||||
2) Add a commit with message "github-release v1.2.3"
|
||||
|
||||
3) Run `git tag v1.2.3` where "1.2.3" stands in for the version you actually
|
||||
want.
|
||||
|
||||
4) Run `make release`. Be sure to have `GITHUB_TOKEN` set in your environment.
|
||||
89
vendor/github.com/aktau/github-release/Gopkg.lock
generated
vendored
Normal file
89
vendor/github.com/aktau/github-release/Gopkg.lock
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
digest = "1:6f9339c912bbdda81302633ad7e99a28dfa5a639c864061f1929510a9a64aa74"
|
||||
name = "github.com/dustin/go-humanize"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "9f541cc9db5d55bce703bd99987c9d5cb8eea45e"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:586ea76dbd0374d6fb649a91d70d652b7fe0ccffb8910a77468e7702e7901f3d"
|
||||
name = "github.com/go-stack/stack"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "2fee6af1a9795aafbe0253a0cfbdf668e1fb8a9a"
|
||||
version = "v1.8.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:5c56664d98f37f0ee54bf572b0b189a3910c34c31052fc7d58b282c449b079fb"
|
||||
name = "github.com/inconshreveable/log15"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "b30bc20e4fd12cec79a9aae62e91cfcf458bd253"
|
||||
version = "v2.15"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:de0adde670b2119824a1252b61a0e989669f8b24af874e399bec0e0538b2f928"
|
||||
name = "github.com/kevinburke/rest"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "0d2892b400f81cdfb979e2f718e6070fae17a507"
|
||||
version = "2.2"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:0109cf4321a15313ec895f42e723e1f76121c6975ea006abfa20012272ec0937"
|
||||
name = "github.com/mattn/go-colorable"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "68e95eba382c972aafde02ead2cd2426a8a92480"
|
||||
version = "v0.1.6"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:0c58d31abe2a2ccb429c559b6292e7df89dcda675456fecc282fa90aa08273eb"
|
||||
name = "github.com/mattn/go-isatty"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "7b513a986450394f7bbf1476909911b3aa3a55ce"
|
||||
version = "v0.0.12"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:f2dda646a25cf3b9f6f6931d86ef0b85b64979697e5833cdcbc0c23f2586d996"
|
||||
name = "github.com/tomnomnom/linkheader"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "02ca5825eb8097f10d9cc53da78481a85ad84e04"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:d1d1683ae67edaebf7e51151f934943bf2f53b71260818d843ab7233aa145533"
|
||||
name = "github.com/voxelbrain/goptions"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "26cb8b04692384f4dc269de3b5fcf3e2ef78573e"
|
||||
version = "2.5.11"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:8cab10971112233c82c83683a517378038eba1c20e71b29c592b73fa212437b3"
|
||||
name = "golang.org/x/sys"
|
||||
packages = [
|
||||
"internal/unsafeheader",
|
||||
"unix",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "bc7a7d42d5c30f4d0fe808715c002826ce2c624e"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
input-imports = [
|
||||
"github.com/dustin/go-humanize",
|
||||
"github.com/kevinburke/rest",
|
||||
"github.com/tomnomnom/linkheader",
|
||||
"github.com/voxelbrain/goptions",
|
||||
]
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
24
vendor/github.com/aktau/github-release/Gopkg.toml
generated
vendored
Normal file
24
vendor/github.com/aktau/github-release/Gopkg.toml
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
# Gopkg.toml example
|
||||
#
|
||||
# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html
|
||||
# for detailed Gopkg.toml documentation.
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/dustin/go-humanize"
|
||||
version = "1.0.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/kevinburke/rest"
|
||||
version = "2.2.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/tomnomnom/linkheader"
|
||||
branch = "master"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/voxelbrain/goptions"
|
||||
version = "2.5.11"
|
||||
|
||||
[prune]
|
||||
go-tests = true
|
||||
unused-packages = true
|
||||
21
vendor/github.com/aktau/github-release/LICENSE
generated
vendored
Normal file
21
vendor/github.com/aktau/github-release/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014-2017 Nicolas Hillegeer
|
||||
Copyright (c) 2020 Meter, Inc.
|
||||
|
||||
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.
|
||||
97
vendor/github.com/aktau/github-release/Makefile
generated
vendored
Normal file
97
vendor/github.com/aktau/github-release/Makefile
generated
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
SHELL=/bin/bash -o pipefail
|
||||
|
||||
LAST_TAG := $(shell git describe --abbrev=0 --tags)
|
||||
|
||||
USER := github-release
|
||||
EXECUTABLE := github-release
|
||||
|
||||
# only include the amd64 binaries, otherwise the github release will become
|
||||
# too big
|
||||
UNIX_EXECUTABLES := \
|
||||
darwin/amd64/$(EXECUTABLE) \
|
||||
freebsd/amd64/$(EXECUTABLE) \
|
||||
linux/amd64/$(EXECUTABLE)
|
||||
WIN_EXECUTABLES := \
|
||||
windows/amd64/$(EXECUTABLE).exe
|
||||
|
||||
COMPRESSED_EXECUTABLES=$(UNIX_EXECUTABLES:%=%.bz2) $(WIN_EXECUTABLES:%.exe=%.zip)
|
||||
COMPRESSED_EXECUTABLE_TARGETS=$(COMPRESSED_EXECUTABLES:%=bin/%)
|
||||
|
||||
UPLOAD_CMD = bin/tmp/$(EXECUTABLE) upload -u $(USER) -r $(EXECUTABLE) -t $(LAST_TAG) -n $(subst /,-,$(FILE)) -f bin/$(FILE)
|
||||
|
||||
all: $(EXECUTABLE)
|
||||
|
||||
# the executable used to perform the upload, dogfooding and all...
|
||||
bin/tmp/$(EXECUTABLE):
|
||||
go build -v -o "$@"
|
||||
|
||||
# arm
|
||||
bin/linux/arm/5/$(EXECUTABLE):
|
||||
GOARM=5 GOARCH=arm GOOS=linux go build -o "$@"
|
||||
bin/linux/arm/7/$(EXECUTABLE):
|
||||
GOARM=7 GOARCH=arm GOOS=linux go build -o "$@"
|
||||
|
||||
# 386
|
||||
bin/darwin/386/$(EXECUTABLE):
|
||||
GOARCH=386 GOOS=darwin go build -o "$@"
|
||||
bin/linux/386/$(EXECUTABLE):
|
||||
GOARCH=386 GOOS=linux go build -o "$@"
|
||||
bin/windows/386/$(EXECUTABLE):
|
||||
GOARCH=386 GOOS=windows go build -o "$@"
|
||||
|
||||
# amd64
|
||||
bin/freebsd/amd64/$(EXECUTABLE):
|
||||
GOARCH=amd64 GOOS=freebsd go build -o "$@"
|
||||
bin/darwin/amd64/$(EXECUTABLE):
|
||||
GOARCH=amd64 GOOS=darwin go build -o "$@"
|
||||
bin/linux/amd64/$(EXECUTABLE):
|
||||
GOARCH=amd64 GOOS=linux go build -o "$@"
|
||||
bin/windows/amd64/$(EXECUTABLE).exe:
|
||||
GOARCH=amd64 GOOS=windows go build -o "$@"
|
||||
|
||||
# compressed artifacts, makes a huge difference (Go executable is ~9MB,
|
||||
# after compressing ~2MB)
|
||||
%.bz2: %
|
||||
bzip2 --keep "$<"
|
||||
%.zip: %.exe
|
||||
zip "$@" "$<"
|
||||
|
||||
# git tag -a v$(RELEASE) -m 'release $(RELEASE)'
|
||||
release: clean
|
||||
ifndef GITHUB_TOKEN
|
||||
@echo "Please set GITHUB_TOKEN in the environment to perform a release"
|
||||
exit 1
|
||||
endif
|
||||
docker run --rm --volume $(PWD)/var/cache:/root/.cache/go-build \
|
||||
--env GITHUB_TOKEN=$(GITHUB_TOKEN) \
|
||||
--volume "$(PWD)":/go/src/github.com/github-release/github-release \
|
||||
--workdir /go/src/github.com/github-release/github-release \
|
||||
meterup/ubuntu-golang:latest \
|
||||
./release \
|
||||
"$(MAKE) bin/tmp/$(EXECUTABLE) $(COMPRESSED_EXECUTABLE_TARGETS) && \
|
||||
git log --format=%B $(LAST_TAG) -1 | \
|
||||
bin/tmp/$(EXECUTABLE) release -u $(USER) -r $(EXECUTABLE) \
|
||||
-t $(LAST_TAG) -n $(LAST_TAG) -d - || true && \
|
||||
$(foreach FILE,$(COMPRESSED_EXECUTABLES),$(UPLOAD_CMD);)"
|
||||
|
||||
# install and/or update all dependencies, run this from the project directory
|
||||
# go get -u ./...
|
||||
# go test -i ./
|
||||
dep:
|
||||
go list -f '{{join .Deps "\n"}}' | xargs go list -e -f '{{if not .Standard}}{{.ImportPath}}{{end}}' | xargs go get -u
|
||||
|
||||
$(EXECUTABLE): dep
|
||||
go build -o "$@"
|
||||
|
||||
install:
|
||||
go install
|
||||
|
||||
clean:
|
||||
rm go-app || true
|
||||
rm $(EXECUTABLE) || true
|
||||
rm -rf bin/
|
||||
|
||||
test:
|
||||
go test ./...
|
||||
|
||||
.PHONY: clean release dep install
|
||||
131
vendor/github.com/aktau/github-release/README.md
generated
vendored
Normal file
131
vendor/github.com/aktau/github-release/README.md
generated
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
github-release
|
||||
==============
|
||||
|
||||
A small commandline app written in Go that allows you to easily create
|
||||
and delete releases of your projects on Github. In addition it allows
|
||||
you to attach files to those releases.
|
||||
|
||||
It interacts with the [github releases API][releases-api]. Though it's entirely
|
||||
possible to [do all these things with cURL][curl], it's not really that
|
||||
user-friendly. For example, you need to first query the API to find the id of
|
||||
the release you want, before you can upload an artifact. `github-release` takes
|
||||
care of those little details.
|
||||
|
||||
[curl]: https://github.com/blog/1645-releases-api-preview
|
||||
[releases-api]: https://developer.github.com/v3/repos/releases
|
||||
|
||||
It might still be a bit rough around the edges, pull requests are
|
||||
welcome!
|
||||
|
||||
How to install
|
||||
==============
|
||||
|
||||
If you don't have the Go toolset installed, and you don't want to, but
|
||||
still want to use the app, you can download binaries for your platform
|
||||
on the [releases
|
||||
page](https://github.com/github-release/github-release/releases/latest). Yes, that's
|
||||
dogfooding, check the makefile!
|
||||
|
||||
If you have Go installed, you can just do:
|
||||
|
||||
```sh
|
||||
go get github.com/github-release/github-release
|
||||
```
|
||||
|
||||
This will automatically download, compile and install the app.
|
||||
|
||||
After that you should have a `github-release` executable in your
|
||||
`$GOPATH/bin`.
|
||||
|
||||
How to use
|
||||
==========
|
||||
|
||||
**NOTE**: for these examples I've [created a github token][token] and set it as
|
||||
the env variable `GITHUB_TOKEN`. `github-release` will automatically pick it up
|
||||
from the environment so that you don't have to pass it as an argument.
|
||||
|
||||
[token]: https://help.github.com/articles/creating-an-access-token-for-command-line-use
|
||||
|
||||
```sh
|
||||
# set your token
|
||||
export GITHUB_TOKEN=...
|
||||
|
||||
# check the help
|
||||
$ github-release --help
|
||||
|
||||
# make your tag and upload
|
||||
$ git tag ... && git push --tags
|
||||
|
||||
# check the current tags and existing releases of the repo
|
||||
$ github-release info -u aktau -r gofinance
|
||||
git tags:
|
||||
- v0.1.0 (commit: https://api.github.com/repos/aktau/gofinance/commits/f562727ce83ce8971a8569a1879219e41d56a756)
|
||||
releases:
|
||||
- v0.1.0, name: 'hoary ungar', description: 'something something dark side 2', id: 166740, tagged: 29/01/2014 at 14:27, published: 30/01/2014 at 16:20, draft: ✔, prerelease: ✗
|
||||
- artifact: github.go, downloads: 0, state: uploaded, type: application/octet-stream, size: 1.9KB, id: 68616
|
||||
|
||||
# create a formal release
|
||||
$ github-release release \
|
||||
--user aktau \
|
||||
--repo gofinance \
|
||||
--tag v0.1.0 \
|
||||
--name "the wolf of source street" \
|
||||
--description "Not a movie, contrary to popular opinion. Still, my first release!" \
|
||||
--pre-release
|
||||
|
||||
# you've made a mistake, but you can edit the release without
|
||||
# having to delete it first (this also means you can edit without having
|
||||
# to upload your files again)
|
||||
$ github-release edit \
|
||||
--user aktau \
|
||||
--repo gofinance \
|
||||
--tag v0.1.0 \
|
||||
--name "Highlander II: The Quickening" \
|
||||
--description "This is the actual description!"
|
||||
|
||||
# upload a file, for example the OSX/AMD64 binary of my gofinance app
|
||||
$ github-release upload \
|
||||
--user aktau \
|
||||
--repo gofinance \
|
||||
--tag v0.1.0 \
|
||||
--name "gofinance-osx-amd64" \
|
||||
--file bin/darwin/amd64/gofinance
|
||||
|
||||
# upload other files...
|
||||
$ github-release upload ...
|
||||
|
||||
# you're not happy with it, so delete it
|
||||
$ github-release delete \
|
||||
--user aktau \
|
||||
--repo gofinance \
|
||||
--tag v0.1.0
|
||||
```
|
||||
|
||||
GitHub Enterprise Support
|
||||
=========================
|
||||
You can point to a different GitHub API endpoint via the environment variable ```GITHUB_API```:
|
||||
|
||||
```
|
||||
export GITHUB_API=http://github.company.com/api/v3
|
||||
```
|
||||
|
||||
Used libraries
|
||||
==============
|
||||
|
||||
| Package | Description | License |
|
||||
| ------------------------------------------------------------------------ | ------------------- | ------- |
|
||||
| [github.com/dustin/go-humanize](https://github.com/dustin/go-humanize) | humanize file sizes | MIT |
|
||||
| [github.com/tomnomnom/linkheader](https://github.com/tomnomnom/linkheader) | GH API pagination | MIT |
|
||||
| [github.com/voxelbrain/goptions](https://github.com/voxelbrain/goptions) | option parsing | BSD |
|
||||
| [github.com/kevinburke/rest](https://github.com/kevinburke/rest) | HTTP client | MIT |
|
||||
|
||||
Todo
|
||||
====
|
||||
|
||||
- Check if an artifact is already uploaded before starting a new upload
|
||||
|
||||
Copyright
|
||||
=========
|
||||
|
||||
Copyright (c) 2014-2017, Nicolas Hillegeer. All rights reserved.
|
||||
Copyright (c) 2020, Meter, Inc. All rights reserved.
|
||||
58
vendor/github.com/aktau/github-release/assets.go
generated
vendored
Normal file
58
vendor/github.com/aktau/github-release/assets.go
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/github-release/github-release/github"
|
||||
)
|
||||
|
||||
const (
|
||||
// GET /repos/:owner/:repo/releases/assets/:id
|
||||
// DELETE /repos/:owner/:repo/releases/assets/:id
|
||||
ASSET_URI = "/repos/%s/%s/releases/assets/%d"
|
||||
|
||||
// API: https://developer.github.com/v3/repos/releases/#list-assets-for-a-release
|
||||
// GET /repos/:owner/:repo/releases/:id/assets
|
||||
ASSET_RELEASE_LIST_URI = "/repos/%s/%s/releases/%d/assets"
|
||||
)
|
||||
|
||||
type Asset struct {
|
||||
Url string `json:"url"`
|
||||
Id int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
ContentType string `json:"content_type"`
|
||||
State string `json:"state"`
|
||||
Size uint64 `json:"size"`
|
||||
Downloads uint64 `json:"download_count"`
|
||||
Created time.Time `json:"created_at"`
|
||||
Published time.Time `json:"published_at"`
|
||||
}
|
||||
|
||||
// findAsset returns the asset if an asset with name can be found in assets,
|
||||
// otherwise returns nil.
|
||||
func findAsset(assets []Asset, name string) *Asset {
|
||||
for _, asset := range assets {
|
||||
if asset.Name == name {
|
||||
return &asset
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Delete sends a HTTP DELETE request for the given asset to Github. Returns
|
||||
// nil if the asset was deleted OR there was nothing to delete.
|
||||
func (a *Asset) Delete(user, repo, token string) error {
|
||||
URL := nvls(EnvApiEndpoint, github.DefaultBaseURL) +
|
||||
fmt.Sprintf(ASSET_URI, user, repo, a.Id)
|
||||
resp, err := github.DoAuthRequest("DELETE", URL, "application/json", token, nil, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete asset %s (ID: %d), HTTP error: %b", a.Name, a.Id, err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusNoContent {
|
||||
return fmt.Errorf("failed to delete asset %s (ID: %d), status: %s", a.Name, a.Id, resp.Status)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
489
vendor/github.com/aktau/github-release/cmd.go
generated
vendored
Normal file
489
vendor/github.com/aktau/github-release/cmd.go
generated
vendored
Normal file
@@ -0,0 +1,489 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/github-release/github-release/github"
|
||||
)
|
||||
|
||||
func infocmd(opt Options) error {
|
||||
user := nvls(opt.Info.User, EnvUser)
|
||||
authUser := nvls(opt.Info.AuthUser, EnvAuthUser)
|
||||
repo := nvls(opt.Info.Repo, EnvRepo)
|
||||
token := nvls(opt.Info.Token, EnvToken)
|
||||
tag := opt.Info.Tag
|
||||
|
||||
if user == "" || repo == "" {
|
||||
return fmt.Errorf("user and repo need to be passed as arguments")
|
||||
}
|
||||
|
||||
// Find regular git tags.
|
||||
foundTags, err := Tags(user, repo, authUser, token)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not fetch tags, %v", err)
|
||||
}
|
||||
if len(foundTags) == 0 {
|
||||
return fmt.Errorf("no tags available for %v/%v", user, repo)
|
||||
}
|
||||
|
||||
tags := foundTags[:0]
|
||||
for _, t := range foundTags {
|
||||
// If the user only requested one tag, filter out the rest.
|
||||
if tag == "" || t.Name == tag {
|
||||
tags = append(tags, t)
|
||||
}
|
||||
}
|
||||
|
||||
renderer := renderInfoText
|
||||
|
||||
if opt.Info.JSON {
|
||||
renderer = renderInfoJSON
|
||||
}
|
||||
|
||||
// List releases + assets.
|
||||
var releases []Release
|
||||
if tag == "" {
|
||||
// Get all releases.
|
||||
vprintf("%v/%v: getting information for all releases\n", user, repo)
|
||||
releases, err = Releases(user, repo, authUser, token)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// Get only one release.
|
||||
vprintf("%v/%v/%v: getting information for the release\n", user, repo, tag)
|
||||
release, err := ReleaseOfTag(user, repo, tag, authUser, token)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
releases = []Release{*release}
|
||||
}
|
||||
|
||||
return renderer(tags, releases)
|
||||
}
|
||||
|
||||
func renderInfoText(tags []Tag, releases []Release) error {
|
||||
fmt.Println("tags:")
|
||||
for _, tag := range tags {
|
||||
fmt.Println("-", &tag)
|
||||
}
|
||||
|
||||
fmt.Println("releases:")
|
||||
for _, release := range releases {
|
||||
fmt.Println("-", &release)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func renderInfoJSON(tags []Tag, releases []Release) error {
|
||||
out := struct {
|
||||
Tags []Tag
|
||||
Releases []Release
|
||||
}{
|
||||
Tags: tags,
|
||||
Releases: releases,
|
||||
}
|
||||
|
||||
enc := json.NewEncoder(os.Stdout)
|
||||
enc.SetIndent("", " ")
|
||||
return enc.Encode(&out)
|
||||
}
|
||||
|
||||
func uploadcmd(opt Options) error {
|
||||
user := nvls(opt.Upload.User, EnvUser)
|
||||
authUser := nvls(opt.Upload.AuthUser, EnvAuthUser)
|
||||
repo := nvls(opt.Upload.Repo, EnvRepo)
|
||||
token := nvls(opt.Upload.Token, EnvToken)
|
||||
tag := opt.Upload.Tag
|
||||
name := opt.Upload.Name
|
||||
label := opt.Upload.Label
|
||||
file := opt.Upload.File
|
||||
|
||||
vprintln("uploading...")
|
||||
|
||||
if file == nil {
|
||||
return fmt.Errorf("provided file was not valid")
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
if err := ValidateCredentials(user, repo, token, tag); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Find the release corresponding to the entered tag, if any.
|
||||
rel, err := ReleaseOfTag(user, repo, tag, authUser, token)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If the user has attempted to upload this asset before, someone could
|
||||
// expect it to be present in the release struct (rel.Assets). However,
|
||||
// we have to separately ask for the specific assets of this release.
|
||||
// Reason: the assets in the Release struct do not contain incomplete
|
||||
// uploads (which regrettably happen often using the Github API). See
|
||||
// issue #26.
|
||||
var assets []Asset
|
||||
client := github.NewClient(authUser, token, nil)
|
||||
client.SetBaseURL(EnvApiEndpoint)
|
||||
err = client.Get(fmt.Sprintf(ASSET_RELEASE_LIST_URI, user, repo, rel.Id), &assets)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Incomplete (failed) uploads will have their state set to new. These
|
||||
// assets are (AFAIK) useless in all cases. The only thing they will do
|
||||
// is prevent the upload of another asset of the same name. To work
|
||||
// around this GH API weirdness, let's just delete assets if:
|
||||
//
|
||||
// 1. Their state is new.
|
||||
// 2. The user explicitly asked to delete/replace the asset with -R.
|
||||
if asset := findAsset(assets, name); asset != nil &&
|
||||
(asset.State == "new" || opt.Upload.Replace) {
|
||||
vprintf("asset (id: %d) already existed in state %s: removing...\n", asset.Id, asset.Name)
|
||||
if err := asset.Delete(user, repo, token); err != nil {
|
||||
return fmt.Errorf("could not replace asset: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
v := url.Values{}
|
||||
v.Set("name", name)
|
||||
if label != "" {
|
||||
v.Set("label", label)
|
||||
}
|
||||
|
||||
url := rel.CleanUploadUrl() + "?" + v.Encode()
|
||||
|
||||
resp, err := github.DoAuthRequest("POST", url, "application/octet-stream",
|
||||
token, nil, file)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't create upload request to %v, %v", url, err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
vprintln("RESPONSE:", resp)
|
||||
|
||||
var r io.Reader = resp.Body
|
||||
if VERBOSITY != 0 {
|
||||
r = io.TeeReader(r, os.Stderr)
|
||||
}
|
||||
var asset *Asset
|
||||
// For HTTP status 201 and 502, Github will return a JSON encoding of
|
||||
// the (partially) created asset.
|
||||
if resp.StatusCode == http.StatusBadGateway || resp.StatusCode == http.StatusCreated {
|
||||
vprintf("ASSET: ")
|
||||
asset = new(Asset)
|
||||
if err := json.NewDecoder(r).Decode(&asset); err != nil {
|
||||
return fmt.Errorf("upload failed (%s), could not unmarshal asset (err: %v)", resp.Status, err)
|
||||
}
|
||||
} else {
|
||||
vprintf("BODY: ")
|
||||
if msg, err := ToMessage(r); err == nil {
|
||||
return fmt.Errorf("could not upload, status code (%s), %v",
|
||||
resp.Status, msg)
|
||||
}
|
||||
return fmt.Errorf("could not upload, status code (%s)", resp.Status)
|
||||
}
|
||||
|
||||
if resp.StatusCode == http.StatusBadGateway {
|
||||
// 502 means the upload failed, but GitHub still retains metadata
|
||||
// (an asset in state "new"). Attempt to delete that now since it
|
||||
// would clutter the list of release assets.
|
||||
vprintf("asset (id: %d) failed to upload, it's now in state %s: removing...\n", asset.Id, asset.Name)
|
||||
if err := asset.Delete(user, repo, token); err != nil {
|
||||
return fmt.Errorf("upload failed (%s), could not delete partially uploaded asset (ID: %d, err: %v) in order to cleanly reset GH API state, please try again", resp.Status, asset.Id, err)
|
||||
}
|
||||
return fmt.Errorf("could not upload, status code (%s)", resp.Status)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func downloadcmd(opt Options) error {
|
||||
user := nvls(opt.Download.User, EnvUser)
|
||||
authUser := nvls(opt.Download.AuthUser, EnvAuthUser)
|
||||
repo := nvls(opt.Download.Repo, EnvRepo)
|
||||
token := nvls(opt.Download.Token, EnvToken)
|
||||
tag := opt.Download.Tag
|
||||
name := opt.Download.Name
|
||||
latest := opt.Download.Latest
|
||||
|
||||
vprintln("downloading...")
|
||||
|
||||
if err := ValidateTarget(user, repo, tag, latest); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Find the release corresponding to the entered tag, if any.
|
||||
var rel *Release
|
||||
var err error
|
||||
if latest {
|
||||
rel, err = LatestRelease(user, repo, authUser, token)
|
||||
} else {
|
||||
rel, err = ReleaseOfTag(user, repo, tag, authUser, token)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
asset := findAsset(rel.Assets, name)
|
||||
if asset == nil {
|
||||
return fmt.Errorf("coud not find asset named %s", name)
|
||||
}
|
||||
|
||||
var resp *http.Response
|
||||
if token == "" {
|
||||
// Use the regular github.com site if we don't have a token.
|
||||
resp, err = http.Get("https://github.com" + fmt.Sprintf("/%s/%s/releases/download/%s/%s", user, repo, tag, name))
|
||||
} else {
|
||||
url := nvls(EnvApiEndpoint, github.DefaultBaseURL) + fmt.Sprintf(ASSET_URI, user, repo, asset.Id)
|
||||
resp, err = github.DoAuthRequest("GET", url, "", token, map[string]string{
|
||||
"Accept": "application/octet-stream",
|
||||
}, nil)
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not fetch releases, %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
vprintln("GET", resp.Request.URL, "->", resp)
|
||||
|
||||
contentLength, err := strconv.ParseInt(resp.Header.Get("Content-Length"), 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("github did not respond with 200 OK but with %v", resp.Status)
|
||||
}
|
||||
|
||||
out := os.Stdout // Pipe the asset to stdout by default.
|
||||
if isCharDevice(out) {
|
||||
// If stdout is a char device, assume it's a TTY (terminal). In this
|
||||
// case, don't pipe th easset to stdout, but create it as a file in
|
||||
// the current working folder.
|
||||
if out, err = os.Create(name); err != nil {
|
||||
return fmt.Errorf("could not create file %s", name)
|
||||
}
|
||||
defer out.Close()
|
||||
}
|
||||
|
||||
return mustCopyN(out, resp.Body, contentLength)
|
||||
}
|
||||
|
||||
// mustCopyN attempts to copy exactly N bytes, if this fails, an error is
|
||||
// returned.
|
||||
func mustCopyN(w io.Writer, r io.Reader, n int64) error {
|
||||
an, err := io.Copy(w, r)
|
||||
if an != n {
|
||||
return fmt.Errorf("data did not match content length %d != %d", an, n)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func ValidateTarget(user, repo, tag string, latest bool) error {
|
||||
if user == "" {
|
||||
return fmt.Errorf("empty user")
|
||||
}
|
||||
if repo == "" {
|
||||
return fmt.Errorf("empty repo")
|
||||
}
|
||||
if tag == "" && !latest {
|
||||
return fmt.Errorf("empty tag")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ValidateCredentials(user, repo, token, tag string) error {
|
||||
if err := ValidateTarget(user, repo, tag, false); err != nil {
|
||||
return err
|
||||
}
|
||||
if token == "" {
|
||||
return fmt.Errorf("empty token")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func releasecmd(opt Options) error {
|
||||
cmdopt := opt.Release
|
||||
user := nvls(cmdopt.User, EnvUser)
|
||||
repo := nvls(cmdopt.Repo, EnvRepo)
|
||||
token := nvls(cmdopt.Token, EnvToken)
|
||||
tag := cmdopt.Tag
|
||||
name := nvls(cmdopt.Name, tag)
|
||||
desc := nvls(cmdopt.Desc, tag)
|
||||
target := nvls(cmdopt.Target)
|
||||
draft := cmdopt.Draft
|
||||
prerelease := cmdopt.Prerelease
|
||||
|
||||
vprintln("releasing...")
|
||||
|
||||
if err := ValidateCredentials(user, repo, token, tag); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check if we need to read the description from stdin.
|
||||
if desc == "-" {
|
||||
b, err := ioutil.ReadAll(os.Stdin)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not read description from stdin: %v", err)
|
||||
}
|
||||
desc = string(b)
|
||||
}
|
||||
|
||||
params := ReleaseCreate{
|
||||
TagName: tag,
|
||||
TargetCommitish: target,
|
||||
Name: name,
|
||||
Body: desc,
|
||||
Draft: draft,
|
||||
Prerelease: prerelease,
|
||||
}
|
||||
|
||||
/* encode params as json */
|
||||
payload, err := json.Marshal(params)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't encode release creation params, %v", err)
|
||||
}
|
||||
reader := bytes.NewReader(payload)
|
||||
|
||||
URL := nvls(EnvApiEndpoint, github.DefaultBaseURL) + fmt.Sprintf("/repos/%s/%s/releases", user, repo)
|
||||
resp, err := github.DoAuthRequest("POST", URL, "application/json", token, nil, reader)
|
||||
if err != nil {
|
||||
return fmt.Errorf("while submitting %v, %v", string(payload), err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
vprintln("RESPONSE:", resp)
|
||||
if resp.StatusCode != http.StatusCreated {
|
||||
if resp.StatusCode == 422 {
|
||||
return fmt.Errorf("github returned %v (this is probably because the release already exists)",
|
||||
resp.Status)
|
||||
}
|
||||
return fmt.Errorf("github returned %v", resp.Status)
|
||||
}
|
||||
|
||||
if VERBOSITY != 0 {
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error while reading response, %v", err)
|
||||
}
|
||||
vprintln("BODY:", string(body))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func editcmd(opt Options) error {
|
||||
cmdopt := opt.Edit
|
||||
user := nvls(cmdopt.User, EnvUser)
|
||||
authUser := nvls(cmdopt.AuthUser, EnvAuthUser)
|
||||
repo := nvls(cmdopt.Repo, EnvRepo)
|
||||
token := nvls(cmdopt.Token, EnvToken)
|
||||
tag := cmdopt.Tag
|
||||
name := nvls(cmdopt.Name, tag)
|
||||
desc := nvls(cmdopt.Desc, tag)
|
||||
draft := cmdopt.Draft
|
||||
prerelease := cmdopt.Prerelease
|
||||
|
||||
vprintln("editing...")
|
||||
|
||||
if err := ValidateCredentials(user, repo, token, tag); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
id, err := IdOfTag(user, repo, tag, authUser, token)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
vprintf("release %v has id %v\n", tag, id)
|
||||
|
||||
// Check if we need to read the description from stdin.
|
||||
if desc == "-" {
|
||||
b, err := ioutil.ReadAll(os.Stdin)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not read description from stdin: %v", err)
|
||||
}
|
||||
desc = string(b)
|
||||
}
|
||||
|
||||
/* the release create struct works for editing releases as well */
|
||||
params := ReleaseCreate{
|
||||
TagName: tag,
|
||||
Name: name,
|
||||
Body: desc,
|
||||
Draft: draft,
|
||||
Prerelease: prerelease,
|
||||
}
|
||||
|
||||
/* encode the parameters as JSON, as required by the github API */
|
||||
payload, err := json.Marshal(params)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't encode release creation params, %v", err)
|
||||
}
|
||||
|
||||
URL := nvls(EnvApiEndpoint, github.DefaultBaseURL) + fmt.Sprintf("/repos/%s/%s/releases/%d", user, repo, id)
|
||||
resp, err := github.DoAuthRequest("PATCH", URL, "application/json", token, nil, bytes.NewReader(payload))
|
||||
if err != nil {
|
||||
return fmt.Errorf("while submitting %v, %v", string(payload), err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
vprintln("RESPONSE:", resp)
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
if resp.StatusCode == 422 {
|
||||
return fmt.Errorf("github returned %v (this is probably because the release already exists)",
|
||||
resp.Status)
|
||||
}
|
||||
return fmt.Errorf("github returned unexpected status code %v", resp.Status)
|
||||
}
|
||||
|
||||
if VERBOSITY != 0 {
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error while reading response, %v", err)
|
||||
}
|
||||
vprintln("BODY:", string(body))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func deletecmd(opt Options) error {
|
||||
user, repo, token, tag := nvls(opt.Delete.User, EnvUser),
|
||||
nvls(opt.Delete.Repo, EnvRepo),
|
||||
nvls(opt.Delete.Token, EnvToken),
|
||||
opt.Delete.Tag
|
||||
authUser := nvls(opt.Delete.AuthUser, EnvAuthUser)
|
||||
vprintln("deleting...")
|
||||
|
||||
id, err := IdOfTag(user, repo, tag, authUser, token)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
vprintf("release %v has id %v\n", tag, id)
|
||||
|
||||
baseURL := nvls(EnvApiEndpoint, github.DefaultBaseURL)
|
||||
resp, err := github.DoAuthRequest("DELETE", baseURL+fmt.Sprintf("/repos/%s/%s/releases/%d",
|
||||
user, repo, id), "application/json", token, nil, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("release deletion failed: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusNoContent {
|
||||
return fmt.Errorf("could not delete the release corresponding to tag %s on repo %s/%s",
|
||||
tag, user, repo)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
6
vendor/github.com/aktau/github-release/commit.go
generated
vendored
Normal file
6
vendor/github.com/aktau/github-release/commit.go
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
package main
|
||||
|
||||
type Commit struct {
|
||||
Sha string `json:"sha"`
|
||||
Url string `json:"url"`
|
||||
}
|
||||
42
vendor/github.com/aktau/github-release/error.go
generated
vendored
Normal file
42
vendor/github.com/aktau/github-release/error.go
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
/* usually when something goes wrong, github sends something like this back */
|
||||
type Message struct {
|
||||
Message string `json:"message"`
|
||||
Errors []GithubError `json:"errors"`
|
||||
}
|
||||
|
||||
type GithubError struct {
|
||||
Resource string `json:"resource"`
|
||||
Code string `json:"code"`
|
||||
Field string `json:"field"`
|
||||
}
|
||||
|
||||
/* transforms a stream into a Message, if it's valid json */
|
||||
func ToMessage(r io.Reader) (*Message, error) {
|
||||
var msg Message
|
||||
if err := json.NewDecoder(r).Decode(&msg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &msg, nil
|
||||
}
|
||||
|
||||
func (m *Message) String() string {
|
||||
str := fmt.Sprintf("msg: %v, errors: ", m.Message)
|
||||
|
||||
errstr := make([]string, len(m.Errors))
|
||||
for idx, err := range m.Errors {
|
||||
errstr[idx] = fmt.Sprintf("[field: %v, code: %v]",
|
||||
err.Field, err.Code)
|
||||
}
|
||||
|
||||
return str + strings.Join(errstr, ", ")
|
||||
}
|
||||
143
vendor/github.com/aktau/github-release/github-release.go
generated
vendored
Normal file
143
vendor/github.com/aktau/github-release/github-release.go
generated
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/github-release/github-release/github"
|
||||
"github.com/voxelbrain/goptions"
|
||||
)
|
||||
|
||||
const GH_URL = "https://github.com"
|
||||
|
||||
type Options struct {
|
||||
Help goptions.Help `goptions:"-h, --help, description='Show this help'"`
|
||||
Verbosity []bool `goptions:"-v, --verbose, description='Be verbose'"`
|
||||
Quiet bool `goptions:"-q, --quiet, description='Do not print anything, even errors (except if --verbose is specified)'"`
|
||||
Version bool `goptions:"--version, description='Print version'"`
|
||||
|
||||
goptions.Verbs
|
||||
Download struct {
|
||||
Token string `goptions:"-s, --security-token, description='Github token ($GITHUB_TOKEN if set). required if repo is private.'"`
|
||||
User string `goptions:"-u, --user, description='Github repo user or organisation (required if $GITHUB_USER not set)'"`
|
||||
AuthUser string `goptions:"-a, --auth-user, description='Username for authenticating to the API (falls back to $GITHUB_AUTH_USER or $GITHUB_USER)'"`
|
||||
Repo string `goptions:"-r, --repo, description='Github repo (required if $GITHUB_REPO not set)'"`
|
||||
Latest bool `goptions:"-l, --latest, description='Download latest release (required if tag is not specified)',mutexgroup='input'"`
|
||||
Tag string `goptions:"-t, --tag, description='Git tag to download from (required if latest is not specified)', mutexgroup='input',obligatory"`
|
||||
Name string `goptions:"-n, --name, description='Name of the file', obligatory"`
|
||||
} `goptions:"download"`
|
||||
Upload struct {
|
||||
Token string `goptions:"-s, --security-token, description='Github token (required if $GITHUB_TOKEN not set)'"`
|
||||
User string `goptions:"-u, --user, description='Github repo user or organisation (required if $GITHUB_USER not set)'"`
|
||||
AuthUser string `goptions:"-a, --auth-user, description='Username for authenticating to the API (falls back to $GITHUB_AUTH_USER or $GITHUB_USER)'"`
|
||||
Repo string `goptions:"-r, --repo, description='Github repo (required if $GITHUB_REPO not set)'"`
|
||||
Tag string `goptions:"-t, --tag, description='Git tag to upload to', obligatory"`
|
||||
Name string `goptions:"-n, --name, description='Name of the file', obligatory"`
|
||||
Label string `goptions:"-l, --label, description='Label (description) of the file'"`
|
||||
File *os.File `goptions:"-f, --file, description='File to upload (use - for stdin)', rdonly, obligatory"`
|
||||
Replace bool `goptions:"-R, --replace, description='Replace asset with same name if it already exists (WARNING: not atomic, failure to upload will remove the original asset too)'"`
|
||||
} `goptions:"upload"`
|
||||
Release struct {
|
||||
Token string `goptions:"-s, --security-token, description='Github token (required if $GITHUB_TOKEN not set)'"`
|
||||
User string `goptions:"-u, --user, description='Github repo user or organisation (required if $GITHUB_USER not set)'"`
|
||||
Repo string `goptions:"-r, --repo, description='Github repo (required if $GITHUB_REPO not set)'"`
|
||||
Tag string `goptions:"-t, --tag, obligatory, description='Git tag to create a release from'"`
|
||||
Name string `goptions:"-n, --name, description='Name of the release (defaults to tag)'"`
|
||||
Desc string `goptions:"-d, --description, description='Release description, use - for reading a description from stdin (defaults to tag)'"`
|
||||
Target string `goptions:"-c, --target, description='Commit SHA or branch to create release of (defaults to the repository default branch)'"`
|
||||
Draft bool `goptions:"--draft, description='The release is a draft'"`
|
||||
Prerelease bool `goptions:"-p, --pre-release, description='The release is a pre-release'"`
|
||||
} `goptions:"release"`
|
||||
Edit struct {
|
||||
Token string `goptions:"-s, --security-token, description='Github token (required if $GITHUB_TOKEN not set)'"`
|
||||
User string `goptions:"-u, --user, description='Github repo user or organisation (required if $GITHUB_USER not set)'"`
|
||||
AuthUser string `goptions:"-a, --auth-user, description='Username for authenticating to the API (falls back to $GITHUB_AUTH_USER or $GITHUB_USER)'"`
|
||||
Repo string `goptions:"-r, --repo, description='Github repo (required if $GITHUB_REPO not set)'"`
|
||||
Tag string `goptions:"-t, --tag, obligatory, description='Git tag to edit the release of'"`
|
||||
Name string `goptions:"-n, --name, description='New name of the release (defaults to tag)'"`
|
||||
Desc string `goptions:"-d, --description, description='New release description, use - for reading a description from stdin (defaults to tag)'"`
|
||||
Draft bool `goptions:"--draft, description='The release is a draft'"`
|
||||
Prerelease bool `goptions:"-p, --pre-release, description='The release is a pre-release'"`
|
||||
} `goptions:"edit"`
|
||||
Delete struct {
|
||||
Token string `goptions:"-s, --security-token, description='Github token (required if $GITHUB_TOKEN not set)'"`
|
||||
User string `goptions:"-u, --user, description='Github repo user or organisation (required if $GITHUB_USER not set)'"`
|
||||
AuthUser string `goptions:"-a, --auth-user, description='Username for authenticating to the API (falls back to $GITHUB_AUTH_USER or $GITHUB_USER)'"`
|
||||
Repo string `goptions:"-r, --repo, description='Github repo (required if $GITHUB_REPO not set)'"`
|
||||
Tag string `goptions:"-t, --tag, obligatory, description='Git tag of release to delete'"`
|
||||
} `goptions:"delete"`
|
||||
Info struct {
|
||||
Token string `goptions:"-s, --security-token, description='Github token ($GITHUB_TOKEN if set). required if repo is private.'"`
|
||||
User string `goptions:"-u, --user, description='Github repo user or organisation (required if $GITHUB_USER not set)'"`
|
||||
AuthUser string `goptions:"-a, --auth-user, description='Username for authenticating to the API (falls back to $GITHUB_AUTH_USER or $GITHUB_USER)'"`
|
||||
Repo string `goptions:"-r, --repo, description='Github repo (required if $GITHUB_REPO not set)'"`
|
||||
Tag string `goptions:"-t, --tag, description='Git tag to query (optional)'"`
|
||||
JSON bool `goptions:"-j, --json, description='Emit info as JSON instead of text'"`
|
||||
} `goptions:"info"`
|
||||
}
|
||||
|
||||
type Command func(Options) error
|
||||
|
||||
var commands = map[goptions.Verbs]Command{
|
||||
"download": downloadcmd,
|
||||
"upload": uploadcmd,
|
||||
"release": releasecmd,
|
||||
"edit": editcmd,
|
||||
"delete": deletecmd,
|
||||
"info": infocmd,
|
||||
}
|
||||
|
||||
var (
|
||||
VERBOSITY = 0
|
||||
)
|
||||
|
||||
var (
|
||||
// The user whose token is being used to authenticate to the API. If unset,
|
||||
// EnvUser is used.
|
||||
EnvAuthUser string
|
||||
EnvToken string
|
||||
EnvUser string
|
||||
EnvRepo string
|
||||
EnvApiEndpoint string
|
||||
)
|
||||
|
||||
func init() {
|
||||
EnvToken = os.Getenv("GITHUB_TOKEN")
|
||||
EnvUser = os.Getenv("GITHUB_USER")
|
||||
EnvAuthUser = os.Getenv("GITHUB_AUTH_USER")
|
||||
EnvRepo = os.Getenv("GITHUB_REPO")
|
||||
EnvApiEndpoint = os.Getenv("GITHUB_API")
|
||||
|
||||
if EnvAuthUser == "" {
|
||||
EnvAuthUser = EnvUser
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
options := Options{}
|
||||
|
||||
goptions.ParseAndFail(&options)
|
||||
|
||||
if options.Version {
|
||||
fmt.Printf("github-release v%s\n", github.VERSION)
|
||||
return
|
||||
}
|
||||
|
||||
if len(options.Verbs) == 0 {
|
||||
goptions.PrintHelp()
|
||||
return
|
||||
}
|
||||
|
||||
VERBOSITY = len(options.Verbosity)
|
||||
github.VERBOSITY = VERBOSITY
|
||||
|
||||
if cmd, found := commands[options.Verbs]; found {
|
||||
err := cmd(options)
|
||||
if err != nil {
|
||||
if !options.Quiet {
|
||||
fmt.Fprintln(os.Stderr, "error:", err)
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
12
vendor/github.com/aktau/github-release/release
generated
vendored
Normal file
12
vendor/github.com/aktau/github-release/release
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
main() {
|
||||
apt-get update && apt-get install zip
|
||||
git branch --set-upstream-to=origin/master release
|
||||
set -x
|
||||
exec /bin/bash -c "$@"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
141
vendor/github.com/aktau/github-release/releases.go
generated
vendored
Normal file
141
vendor/github.com/aktau/github-release/releases.go
generated
vendored
Normal file
@@ -0,0 +1,141 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/github-release/github-release/github"
|
||||
"github.com/dustin/go-humanize"
|
||||
)
|
||||
|
||||
const (
|
||||
RELEASE_LIST_URI = "/repos/%s/%s/releases"
|
||||
RELEASE_LATEST_URI = "/repos/%s/%s/releases/latest"
|
||||
RELEASE_DATE_FORMAT = "02/01/2006 at 15:04"
|
||||
)
|
||||
|
||||
type Release struct {
|
||||
Url string `json:"url"`
|
||||
PageUrl string `json:"html_url"`
|
||||
UploadUrl string `json:"upload_url"`
|
||||
Id int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"body"`
|
||||
TagName string `json:"tag_name"`
|
||||
Draft bool `json:"draft"`
|
||||
Prerelease bool `json:"prerelease"`
|
||||
Created *time.Time `json:"created_at"`
|
||||
Published *time.Time `json:"published_at"`
|
||||
Assets []Asset `json:"assets"`
|
||||
}
|
||||
|
||||
func (r *Release) CleanUploadUrl() string {
|
||||
bracket := strings.Index(r.UploadUrl, "{")
|
||||
|
||||
if bracket == -1 {
|
||||
return r.UploadUrl
|
||||
}
|
||||
|
||||
return r.UploadUrl[0:bracket]
|
||||
}
|
||||
|
||||
func (r *Release) String() string {
|
||||
str := make([]string, len(r.Assets)+1)
|
||||
str[0] = fmt.Sprintf(
|
||||
"%s, name: '%s', description: '%s', id: %d, tagged: %s, published: %s, draft: %v, prerelease: %v",
|
||||
r.TagName, r.Name, r.Description, r.Id,
|
||||
timeFmtOr(r.Created, RELEASE_DATE_FORMAT, ""),
|
||||
timeFmtOr(r.Published, RELEASE_DATE_FORMAT, ""),
|
||||
Mark(r.Draft), Mark(r.Prerelease))
|
||||
|
||||
for idx, asset := range r.Assets {
|
||||
str[idx+1] = fmt.Sprintf(" - artifact: %s, downloads: %d, state: %s, type: %s, size: %s, id: %d",
|
||||
asset.Name, asset.Downloads, asset.State, asset.ContentType,
|
||||
humanize.Bytes(asset.Size), asset.Id)
|
||||
}
|
||||
|
||||
return strings.Join(str, "\n")
|
||||
}
|
||||
|
||||
type ReleaseCreate struct {
|
||||
TagName string `json:"tag_name"`
|
||||
TargetCommitish string `json:"target_commitish,omitempty"`
|
||||
Name string `json:"name"`
|
||||
Body string `json:"body"`
|
||||
Draft bool `json:"draft"`
|
||||
Prerelease bool `json:"prerelease"`
|
||||
}
|
||||
|
||||
func Releases(user, repo, authUser, token string) ([]Release, error) {
|
||||
var releases []Release
|
||||
client := github.NewClient(authUser, token, nil)
|
||||
client.SetBaseURL(EnvApiEndpoint)
|
||||
err := client.Get(fmt.Sprintf(RELEASE_LIST_URI, user, repo), &releases)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return releases, nil
|
||||
}
|
||||
|
||||
func latestReleaseApi(user, repo, authUser, token string) (*Release, error) {
|
||||
var release Release
|
||||
client := github.NewClient(authUser, token, nil)
|
||||
client.SetBaseURL(EnvApiEndpoint)
|
||||
return &release, client.Get(fmt.Sprintf(RELEASE_LATEST_URI, user, repo), &release)
|
||||
}
|
||||
|
||||
func LatestRelease(user, repo, authUser, token string) (*Release, error) {
|
||||
// If latestReleaseApi DOESN'T give an error, return the release.
|
||||
if latestRelease, err := latestReleaseApi(user, repo, authUser, token); err == nil {
|
||||
return latestRelease, nil
|
||||
}
|
||||
|
||||
// The enterprise api doesnt support the latest release endpoint. Get
|
||||
// all releases and compare the published date to get the latest.
|
||||
releases, err := Releases(user, repo, authUser, token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var latestRelIndex = -1
|
||||
maxDate := time.Time{}
|
||||
for i, release := range releases {
|
||||
if relDate := *release.Published; relDate.After(maxDate) {
|
||||
maxDate = relDate
|
||||
latestRelIndex = i
|
||||
}
|
||||
}
|
||||
if latestRelIndex == -1 {
|
||||
return nil, fmt.Errorf("could not find the latest release")
|
||||
}
|
||||
|
||||
vprintln("Scanning ", len(releases), "releases, latest release is", releases[latestRelIndex])
|
||||
return &releases[latestRelIndex], nil
|
||||
}
|
||||
|
||||
func ReleaseOfTag(user, repo, tag, authUser, token string) (*Release, error) {
|
||||
releases, err := Releases(user, repo, authUser, token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, release := range releases {
|
||||
if release.TagName == tag {
|
||||
return &release, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("could not find the release corresponding to tag %s", tag)
|
||||
}
|
||||
|
||||
/* find the release-id of the specified tag */
|
||||
func IdOfTag(user, repo, tag, authUser, token string) (int, error) {
|
||||
release, err := ReleaseOfTag(user, repo, tag, authUser, token)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return release.Id, nil
|
||||
}
|
||||
30
vendor/github.com/aktau/github-release/tags.go
generated
vendored
Normal file
30
vendor/github.com/aktau/github-release/tags.go
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/github-release/github-release/github"
|
||||
)
|
||||
|
||||
const (
|
||||
TAGS_URI = "/repos/%s/%s/tags"
|
||||
)
|
||||
|
||||
type Tag struct {
|
||||
Name string `json:"name"`
|
||||
Commit Commit `json:"commit"`
|
||||
ZipBallUrl string `json:"zipball_url"`
|
||||
TarBallUrl string `json:"tarball_url"`
|
||||
}
|
||||
|
||||
func (t *Tag) String() string {
|
||||
return t.Name + " (commit: " + t.Commit.Url + ")"
|
||||
}
|
||||
|
||||
// Get the tags associated with a repo.
|
||||
func Tags(user, repo, authUser, token string) ([]Tag, error) {
|
||||
var tags []Tag
|
||||
client := github.NewClient(authUser, token, nil)
|
||||
client.SetBaseURL(EnvApiEndpoint)
|
||||
return tags, client.Get(fmt.Sprintf(TAGS_URI, user, repo), &tags)
|
||||
}
|
||||
9
vendor/github.com/aktau/github-release/term.go
generated
vendored
Normal file
9
vendor/github.com/aktau/github-release/term.go
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
package main
|
||||
|
||||
func Mark(ok bool) string {
|
||||
if ok {
|
||||
return "✔"
|
||||
} else {
|
||||
return "✗"
|
||||
}
|
||||
}
|
||||
52
vendor/github.com/aktau/github-release/util.go
generated
vendored
Normal file
52
vendor/github.com/aktau/github-release/util.go
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
/* nvls returns the first value in xs that is not empty. */
|
||||
func nvls(xs ...string) string {
|
||||
for _, s := range xs {
|
||||
if s != "" {
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func vprintln(a ...interface{}) (int, error) {
|
||||
if VERBOSITY > 0 {
|
||||
return fmt.Fprintln(os.Stderr, a...)
|
||||
}
|
||||
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func vprintf(format string, a ...interface{}) (int, error) {
|
||||
if VERBOSITY > 0 {
|
||||
return fmt.Fprintf(os.Stderr, format, a...)
|
||||
}
|
||||
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// formats time `t` as `fmt` if it is not nil, otherwise returns `def`
|
||||
func timeFmtOr(t *time.Time, fmt, def string) string {
|
||||
if t == nil {
|
||||
return def
|
||||
}
|
||||
return t.Format(fmt)
|
||||
}
|
||||
|
||||
// isCharDevice returns true if f is a character device (panics if f can't
|
||||
// be stat'ed).
|
||||
func isCharDevice(f *os.File) bool {
|
||||
stat, err := f.Stat()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return (stat.Mode() & os.ModeCharDevice) != 0
|
||||
}
|
||||
1
vendor/github.com/aktau/github-release/version.go
generated
vendored
Normal file
1
vendor/github.com/aktau/github-release/version.go
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
package main
|
||||
15
vendor/github.com/andygrunwald/go-jira/.travis.yml
generated
vendored
15
vendor/github.com/andygrunwald/go-jira/.travis.yml
generated
vendored
@@ -3,15 +3,18 @@ language: go
|
||||
sudo: false
|
||||
|
||||
go:
|
||||
- 1.4
|
||||
- 1.5
|
||||
- 1.6
|
||||
- 1.7
|
||||
- 1.8
|
||||
- 1.9
|
||||
- "1.9.x"
|
||||
- "1.10.x"
|
||||
- "1.11.x"
|
||||
- "1.12.x"
|
||||
- "1.13.x"
|
||||
|
||||
before_install:
|
||||
- go get -t ./...
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- go: 1.13.x
|
||||
|
||||
script:
|
||||
- GOMAXPROCS=4 GORACE="halt_on_error=1" go test -race -v ./...
|
||||
|
||||
81
vendor/github.com/andygrunwald/go-jira/CHANGELOG.md
generated
vendored
Normal file
81
vendor/github.com/andygrunwald/go-jira/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
||||
|
||||
## [1.12.0](https://github.com/andygrunwald/go-jira/compare/v1.11.1...v1.12.0) (2019-12-14)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add IssueLinkTypeService with GetList and test ([261889a](https://github.com/andygrunwald/go-jira/commit/261889adc63623fcea0fa8cab0d5da26eec37e68))
|
||||
* add worklog update method ([9ff562a](https://github.com/andygrunwald/go-jira/commit/9ff562ae3ea037961f277be10412ad0a42ff8a6f))
|
||||
* Implement get remote links method ([1946cac](https://github.com/andygrunwald/go-jira/commit/1946cac0fe6ee91f784e3dda3c12f3f30f7115b8))
|
||||
* Implement issue link type DELETE ([e37cc6c](https://github.com/andygrunwald/go-jira/commit/e37cc6c6897830492c070667ab8b68bd85683fc3))
|
||||
* Implement issue link type GET ([57538b9](https://github.com/andygrunwald/go-jira/commit/57538b926c558e97940760a30bdc16cdd37ef4f1))
|
||||
* Implement issue link type POST ([75b9df8](https://github.com/andygrunwald/go-jira/commit/75b9df8b01557f01dc318d33c0bc2841a9c084eb))
|
||||
* Implement issue link type PUT ([48a15c1](https://github.com/andygrunwald/go-jira/commit/48a15c10443a3cff78f0fb2c8034dd772320e238))
|
||||
* provide access to issue transitions loaded from JIRA API ([7530b7c](https://github.com/andygrunwald/go-jira/commit/7530b7cd8266d82cdb4afe831518986772e742ba))
|
||||
|
||||
### [1.11.1](https://github.com/andygrunwald/go-jira/compare/v1.11.0...v1.11.1) (2019-10-17)
|
||||
|
||||
## [1.11.0](https://github.com/andygrunwald/go-jira/compare/v1.10.0...v1.11.0) (2019-10-17)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add AccountID and AccountType to GroupMember struct ([216e005](https://github.com/andygrunwald/go-jira/commit/216e0056d6385eba9d31cb37e6ff64314860d2cc))
|
||||
* Add AccountType and Locale to User struct ([52ab347](https://github.com/andygrunwald/go-jira/commit/52ab34790307144087f0d9bf86c93a2b2209fe46))
|
||||
* Add GetAllStatuses ([afc96b1](https://github.com/andygrunwald/go-jira/commit/afc96b18d17b77e32cec9e1ac7e4f5dec7e627f5))
|
||||
* Add GetMyFilters to FilterService ([ebae19d](https://github.com/andygrunwald/go-jira/commit/ebae19dda6afd0e54578f30300bc36012381e99b))
|
||||
* Add Search to FilterService ([38a755b](https://github.com/andygrunwald/go-jira/commit/38a755b407cd70d11fe2e2897d814552ca29ab51))
|
||||
* add support for JWT auth with qsh needed by add-ons ([a8bdfed](https://github.com/andygrunwald/go-jira/commit/a8bdfed27ff42a9bb0468b8cf192871780919def))
|
||||
* AddGetBoardConfiguration ([fd698c5](https://github.com/andygrunwald/go-jira/commit/fd698c57163f248f21285d5ebc6a3bb60d46694f))
|
||||
* Replace http.Client with interface for extensibility ([b59a65c](https://github.com/andygrunwald/go-jira/commit/b59a65c365dcefd42e135579e9b7ce9c9c006489))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fix fixversion description tag ([8383e2f](https://github.com/andygrunwald/go-jira/commit/8383e2f5f145d04f6bcdb47fb12a95b58bdcedfa))
|
||||
* Fix typos in filter_test.go ([e9a261c](https://github.com/andygrunwald/go-jira/commit/e9a261c52249073345e5895b22e2cf4d7286497a))
|
||||
|
||||
# [1.10.0](https://github.com/andygrunwald/go-jira/compare/v1.9.0...v1.10.0) (2019-05-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* empty SearchOptions causing malformed request ([b3bf8c2](https://github.com/andygrunwald/go-jira/commit/b3bf8c2))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* added DeleteAttachment ([e93c0e1](https://github.com/andygrunwald/go-jira/commit/e93c0e1))
|
||||
|
||||
|
||||
|
||||
# [1.9.0](https://github.com/andygrunwald/go-jira/compare/v1.8.0...v1.9.0) (2019-05-19)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **issues:** Added support for AddWorklog and GetWorklogs ([1ebd7e7](https://github.com/andygrunwald/go-jira/commit/1ebd7e7))
|
||||
|
||||
|
||||
|
||||
# [1.8.0](https://github.com/andygrunwald/go-jira/compare/v1.7.0...v1.8.0) (2019-05-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Add PriorityService to the main ([8491cb0](https://github.com/andygrunwald/go-jira/commit/8491cb0))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **filter:** Add GetFavouriteList to FilterService. ([645898e](https://github.com/andygrunwald/go-jira/commit/645898e))
|
||||
* Add get all priorities ([1c63e25](https://github.com/andygrunwald/go-jira/commit/1c63e25))
|
||||
* Add ResolutionService to retrieve resolutions ([fb1ce22](https://github.com/andygrunwald/go-jira/commit/fb1ce22))
|
||||
* Add status category constants ([6223ddd](https://github.com/andygrunwald/go-jira/commit/6223ddd))
|
||||
* Add StatusCategory GetList ([049a756](https://github.com/andygrunwald/go-jira/commit/049a756))
|
||||
|
||||
|
||||
|
||||
36
vendor/github.com/andygrunwald/go-jira/Gopkg.lock
generated
vendored
36
vendor/github.com/andygrunwald/go-jira/Gopkg.lock
generated
vendored
@@ -1,36 +0,0 @@
|
||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/fatih/structs"
|
||||
packages = ["."]
|
||||
revision = "a720dfa8df582c51dee1b36feabb906bde1588bd"
|
||||
version = "v1.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/google/go-querystring"
|
||||
packages = ["query"]
|
||||
revision = "53e6ce116135b80d037921a7fdd5138cf32d7a8a"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/pkg/errors"
|
||||
packages = ["."]
|
||||
revision = "645ef00459ed84a119197bfb8d8205042c6df63d"
|
||||
version = "v0.8.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/trivago/tgo"
|
||||
packages = [
|
||||
"tcontainer",
|
||||
"treflect"
|
||||
]
|
||||
revision = "e4d1ddd28c17dd89ed26327cf69fded22060671b"
|
||||
version = "v1.0.1"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "e84ca9eea6d233e0947b0d760913db2983fd4cbf6fd0d8690c737a71affb635c"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
46
vendor/github.com/andygrunwald/go-jira/Gopkg.toml
generated
vendored
46
vendor/github.com/andygrunwald/go-jira/Gopkg.toml
generated
vendored
@@ -1,46 +0,0 @@
|
||||
# Gopkg.toml example
|
||||
#
|
||||
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
|
||||
# for detailed Gopkg.toml documentation.
|
||||
#
|
||||
# required = ["github.com/user/thing/cmd/thing"]
|
||||
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project"
|
||||
# version = "1.0.0"
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project2"
|
||||
# branch = "dev"
|
||||
# source = "github.com/myfork/project2"
|
||||
#
|
||||
# [[override]]
|
||||
# name = "github.com/x/y"
|
||||
# version = "2.4.0"
|
||||
#
|
||||
# [prune]
|
||||
# non-go = false
|
||||
# go-tests = true
|
||||
# unused-packages = true
|
||||
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/fatih/structs"
|
||||
version = "1.0.0"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/google/go-querystring"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/pkg/errors"
|
||||
version = "0.8.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/trivago/tgo"
|
||||
version = "1.0.1"
|
||||
|
||||
[prune]
|
||||
go-tests = true
|
||||
unused-packages = true
|
||||
15
vendor/github.com/andygrunwald/go-jira/PULL_REQUEST_TEMPLATE.md
generated
vendored
Normal file
15
vendor/github.com/andygrunwald/go-jira/PULL_REQUEST_TEMPLATE.md
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
# PR Description
|
||||
|
||||
_What does this fix or add?_
|
||||
|
||||
# Checklist
|
||||
|
||||
* [ ] Tests added
|
||||
* [ ] Good Path
|
||||
* [ ] Error Path
|
||||
* [ ] Commits follow conventions described here:
|
||||
* [ ] [https://conventionalcommits.org/en/v1.0.0-beta.4/#summary](https://conventionalcommits.org/en/v1.0.0-beta.4/#summary)
|
||||
* [ ] [https://chris.beams.io/posts/git-commit/#seven-rules](https://chris.beams.io/posts/git-commit/#seven-rules)
|
||||
* [ ] Commits are squashed such that
|
||||
* [ ] There is 1 commit per isolated change
|
||||
* [ ] I've not made extraneous commits/changes that are unrelated to my change.
|
||||
76
vendor/github.com/andygrunwald/go-jira/README.md
generated
vendored
76
vendor/github.com/andygrunwald/go-jira/README.md
generated
vendored
@@ -17,15 +17,18 @@
|
||||
|
||||
This package is not JIRA API complete (yet), but you can call every API endpoint you want. See [Call a not implemented API endpoint](#call-a-not-implemented-api-endpoint) how to do this. For all possible API endpoints of JIRA have a look at [latest JIRA REST API documentation](https://docs.atlassian.com/jira/REST/latest/).
|
||||
|
||||
## Compatible JIRA versions
|
||||
## Requirements
|
||||
|
||||
This package was tested against JIRA v6.3.4 and v7.1.2.
|
||||
* Go >= 1.8
|
||||
* JIRA v6.3.4 & v7.1.2.
|
||||
|
||||
## Installation
|
||||
|
||||
It is go gettable
|
||||
|
||||
$ go get github.com/andygrunwald/go-jira
|
||||
```bash
|
||||
go get github.com/andygrunwald/go-jira
|
||||
```
|
||||
|
||||
For stable versions you can use one of our tags with [gopkg.in](http://labix.org/gopkg.in). E.g.
|
||||
|
||||
@@ -40,8 +43,10 @@ import (
|
||||
|
||||
(optional) to run unit / example tests:
|
||||
|
||||
$ cd $GOPATH/src/github.com/andygrunwald/go-jira
|
||||
$ go test -v ./...
|
||||
```bash
|
||||
cd $GOPATH/src/github.com/andygrunwald/go-jira
|
||||
go test -v ./...
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
@@ -89,13 +94,13 @@ For convenience, capability for basic and cookie-based authentication is include
|
||||
|
||||
#### Basic auth example
|
||||
|
||||
A more thorough, [runnable example](examples/basicauth/main.go) is provided in the examples directory.
|
||||
A more thorough, [runnable example](examples/basicauth/main.go) is provided in the examples directory. **It's worth noting that using passwords in basic auth is now deprecated and will be removed.** Jira gives you the ability to [create tokens now.](https://confluence.atlassian.com/cloud/api-tokens-938839638.html)
|
||||
|
||||
```go
|
||||
func main() {
|
||||
tp := jira.BasicAuthTransport{
|
||||
Username: "username",
|
||||
Password: "password",
|
||||
Password: "token",
|
||||
}
|
||||
|
||||
client, err := jira.NewClient(tp.Client(), "https://my.jira.com")
|
||||
@@ -106,25 +111,10 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
#### Authenticate with session cookie
|
||||
#### Authenticate with session cookie [DEPRECATED]
|
||||
|
||||
A more thorough, [runnable example](examples/cookieauth/main.go) is provided in the examples directory.
|
||||
JIRA [deprecated this authentication method.](https://developer.atlassian.com/cloud/jira/platform/deprecation-notice-basic-auth-and-cookie-based-auth/) It's not longer available for use.
|
||||
|
||||
Note: The `AuthURL` is almost always going to have the path `/rest/auth/1/session`
|
||||
|
||||
```go
|
||||
tp := jira.CookieAuthTransport{
|
||||
Username: "username",
|
||||
Password: "password",
|
||||
AuthURL: "https://my.jira.com/rest/auth/1/session",
|
||||
}
|
||||
|
||||
client, err := jira.NewClient(tp.Client(), "https://my.jira.com")
|
||||
u, _, err := client.User.Get("admin")
|
||||
|
||||
fmt.Printf("\nEmail: %v\nSuccess!\n", u.EmailAddress)
|
||||
}
|
||||
```
|
||||
|
||||
#### Authenticate with OAuth
|
||||
|
||||
@@ -146,10 +136,9 @@ import (
|
||||
|
||||
func main() {
|
||||
base := "https://my.jira.com"
|
||||
tp := jira.CookieAuthTransport{
|
||||
tp := jira.BasicAuthTransport{
|
||||
Username: "username",
|
||||
Password: "password",
|
||||
AuthURL: fmt.Sprintf("%s/rest/auth/1/session", base),
|
||||
Password: "token",
|
||||
}
|
||||
|
||||
jiraClient, err := jira.NewClient(tp.Client(), base)
|
||||
@@ -200,17 +189,16 @@ import (
|
||||
|
||||
func main() {
|
||||
base := "https://my.jira.com"
|
||||
tp := jira.CookieAuthTransport{
|
||||
tp := jira.BasicAuthTransport{
|
||||
Username: "username",
|
||||
Password: "password",
|
||||
AuthURL: fmt.Sprintf("%s/rest/auth/1/session", base),
|
||||
Password: "token",
|
||||
}
|
||||
|
||||
jiraClient, err := jira.NewClient(tp.Client(), base)
|
||||
req, _ := jiraClient.NewRequest("GET", "/rest/api/2/project", nil)
|
||||
req, _ := jiraClient.NewRequest("GET", "rest/api/2/project", nil)
|
||||
|
||||
projects := new([]jira.Project)
|
||||
_, err := jiraClient.Do(req, projects)
|
||||
_, err = jiraClient.Do(req, projects)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -242,6 +230,8 @@ These services own a responsibility of the single endpoints / usecases of JIRA.
|
||||
|
||||
## Contribution
|
||||
|
||||
We ❤️ PR's
|
||||
|
||||
Contribution, in any kind of way, is highly welcome!
|
||||
It doesn't matter if you are not able to write code.
|
||||
Creating issues or holding talks and help other people to use [go-jira](https://github.com/andygrunwald/go-jira) is contribution, too!
|
||||
@@ -250,15 +240,15 @@ A few examples:
|
||||
* Correct typos in the README / documentation
|
||||
* Reporting bugs
|
||||
* Implement a new feature or endpoint
|
||||
* Sharing the love if [go-jira](https://github.com/andygrunwald/go-jira) and help people to get use to it
|
||||
* Sharing the love of [go-jira](https://github.com/andygrunwald/go-jira) and help people to get use to it
|
||||
|
||||
If you are new to pull requests, checkout [Collaborating on projects using issues and pull requests / Creating a pull request](https://help.github.com/articles/creating-a-pull-request/).
|
||||
|
||||
### Dependency management
|
||||
|
||||
`go-jira` uses `dep` for dependency management. After cloning the repo, it's easy to make sure you have the correct dependencies by running `dep ensure`.
|
||||
`go-jira` uses `go modules` for dependency management. After cloning the repo, it's easy to make sure you have the correct dependencies by running `go mod tidy`.
|
||||
|
||||
For adding new dependencies, updating dependencies, and other operations, the [Daily Dep](https://golang.github.io/dep/docs/daily-dep.html) is a good place to start.
|
||||
For adding new dependencies, updating dependencies, and other operations, the [Daily workflow](https://github.com/golang/go/wiki/Modules#daily-workflow) is a good place to start.
|
||||
|
||||
### Sandbox environment for testing
|
||||
|
||||
@@ -266,6 +256,22 @@ Jira offers sandbox test environments at http://go.atlassian.com/cloud-dev.
|
||||
|
||||
You can read more about them at https://developer.atlassian.com/blog/2016/04/cloud-ecosystem-dev-env/.
|
||||
|
||||
## Releasing
|
||||
|
||||
Install `standard-version`
|
||||
```bash
|
||||
npm i -g standard-version
|
||||
```
|
||||
|
||||
```bash
|
||||
standard-version
|
||||
git push --tags
|
||||
```
|
||||
|
||||
Manually copy/paste text from changelog (for this new version) into the release on Github.com. E.g.
|
||||
|
||||
[https://github.com/andygrunwald/go-jira/releases/edit/v1.11.0](https://github.com/andygrunwald/go-jira/releases/edit/v1.11.0)
|
||||
|
||||
## License
|
||||
|
||||
This project is released under the terms of the [MIT license](http://en.wikipedia.org/wiki/MIT_License).
|
||||
|
||||
127
vendor/github.com/andygrunwald/go-jira/board.go
generated
vendored
127
vendor/github.com/andygrunwald/go-jira/board.go
generated
vendored
@@ -2,6 +2,7 @@ package jira
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -34,7 +35,7 @@ type Board struct {
|
||||
type BoardListOptions struct {
|
||||
// BoardType filters results to boards of the specified type.
|
||||
// Valid values: scrum, kanban.
|
||||
BoardType string `url:"boardType,omitempty"`
|
||||
BoardType string `url:"type,omitempty"`
|
||||
// Name filters results to boards that match or partially match the specified name.
|
||||
Name string `url:"name,omitempty"`
|
||||
// ProjectKeyOrID filters results to boards that are relevant to a project.
|
||||
@@ -44,9 +45,21 @@ type BoardListOptions struct {
|
||||
SearchOptions
|
||||
}
|
||||
|
||||
// Wrapper struct for search result
|
||||
type sprintsResult struct {
|
||||
Sprints []Sprint `json:"values" structs:"values"`
|
||||
// GetAllSprintsOptions specifies the optional parameters to the BoardService.GetList
|
||||
type GetAllSprintsOptions struct {
|
||||
// State filters results to sprints in the specified states, comma-separate list
|
||||
State string `url:"state,omitempty"`
|
||||
|
||||
SearchOptions
|
||||
}
|
||||
|
||||
// SprintsList reflects a list of agile sprints
|
||||
type SprintsList struct {
|
||||
MaxResults int `json:"maxResults" structs:"maxResults"`
|
||||
StartAt int `json:"startAt" structs:"startAt"`
|
||||
Total int `json:"total" structs:"total"`
|
||||
IsLast bool `json:"isLast" structs:"isLast"`
|
||||
Values []Sprint `json:"values" structs:"values"`
|
||||
}
|
||||
|
||||
// Sprint represents a sprint on JIRA agile board
|
||||
@@ -61,12 +74,65 @@ type Sprint struct {
|
||||
State string `json:"state" structs:"state"`
|
||||
}
|
||||
|
||||
// BoardConfiguration represents a boardConfiguration of a jira board
|
||||
type BoardConfiguration struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Self string `json:"self"`
|
||||
Location BoardConfigurationLocation `json:"location"`
|
||||
Filter BoardConfigurationFilter `json:"filter"`
|
||||
SubQuery BoardConfigurationSubQuery `json:"subQuery"`
|
||||
ColumnConfig BoardConfigurationColumnConfig `json:"columnConfig"`
|
||||
}
|
||||
|
||||
// BoardConfigurationFilter reference to the filter used by the given board.
|
||||
type BoardConfigurationFilter struct {
|
||||
ID string `json:"id"`
|
||||
Self string `json:"self"`
|
||||
}
|
||||
|
||||
// BoardConfigurationSubQuery (Kanban only) - JQL subquery used by the given board.
|
||||
type BoardConfigurationSubQuery struct {
|
||||
Query string `json:"query"`
|
||||
}
|
||||
|
||||
// BoardConfigurationLocation reference to the container that the board is located in
|
||||
type BoardConfigurationLocation struct {
|
||||
Type string `json:"type"`
|
||||
Key string `json:"key"`
|
||||
ID string `json:"id"`
|
||||
Self string `json:"self"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// BoardConfigurationColumnConfig lists the columns for a given board in the order defined in the column configuration
|
||||
// with constrainttype (none, issueCount, issueCountExclSubs)
|
||||
type BoardConfigurationColumnConfig struct {
|
||||
Columns []BoardConfigurationColumn `json:"columns"`
|
||||
ConstraintType string `json:"constraintType"`
|
||||
}
|
||||
|
||||
// BoardConfigurationColumn lists the name of the board with the statuses that maps to a particular column
|
||||
type BoardConfigurationColumn struct {
|
||||
Name string `json:"name"`
|
||||
Status []BoardConfigurationColumnStatus `json:"statuses"`
|
||||
}
|
||||
|
||||
// BoardConfigurationColumnStatus represents a status in the column configuration
|
||||
type BoardConfigurationColumnStatus struct {
|
||||
ID string `json:"id"`
|
||||
Self string `json:"self"`
|
||||
}
|
||||
|
||||
// GetAllBoards will returns all boards. This only includes boards that the user has permission to view.
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board-getAllBoards
|
||||
func (s *BoardService) GetAllBoards(opt *BoardListOptions) (*BoardsList, *Response, error) {
|
||||
apiEndpoint := "rest/agile/1.0/board"
|
||||
url, err := addOptions(apiEndpoint, opt)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
req, err := s.client.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@@ -145,22 +211,65 @@ func (s *BoardService) DeleteBoard(boardID int) (*Board, *Response, error) {
|
||||
return nil, resp, err
|
||||
}
|
||||
|
||||
// GetAllSprints will returns all sprints from a board, for a given board Id.
|
||||
// GetAllSprints will return all sprints from a board, for a given board Id.
|
||||
// This only includes sprints that the user has permission to view.
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board/{boardId}/sprint
|
||||
func (s *BoardService) GetAllSprints(boardID string) ([]Sprint, *Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("rest/agile/1.0/board/%s/sprint", boardID)
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
id, err := strconv.Atoi(boardID)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
result := new(sprintsResult)
|
||||
result, response, err := s.GetAllSprintsWithOptions(id, &GetAllSprintsOptions{})
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return result.Values, response, nil
|
||||
}
|
||||
|
||||
// GetAllSprintsWithOptions will return sprints from a board, for a given board Id and filtering options
|
||||
// This only includes sprints that the user has permission to view.
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board/{boardId}/sprint
|
||||
func (s *BoardService) GetAllSprintsWithOptions(boardID int, options *GetAllSprintsOptions) (*SprintsList, *Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("rest/agile/1.0/board/%d/sprint", boardID)
|
||||
url, err := addOptions(apiEndpoint, options)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
req, err := s.client.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
result := new(SprintsList)
|
||||
resp, err := s.client.Do(req, result)
|
||||
if err != nil {
|
||||
err = NewJiraError(resp, err)
|
||||
}
|
||||
|
||||
return result.Sprints, resp, err
|
||||
return result, resp, err
|
||||
}
|
||||
|
||||
// GetBoardConfiguration will return a board configuration for a given board Id
|
||||
// Jira API docs:https://developer.atlassian.com/cloud/jira/software/rest/#api-rest-agile-1-0-board-boardId-configuration-get
|
||||
func (s *BoardService) GetBoardConfiguration(boardID int) (*BoardConfiguration, *Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("rest/agile/1.0/board/%d/configuration", boardID)
|
||||
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
result := new(BoardConfiguration)
|
||||
resp, err := s.client.Do(req, result)
|
||||
if err != nil {
|
||||
err = NewJiraError(resp, err)
|
||||
}
|
||||
|
||||
return result, resp, err
|
||||
|
||||
}
|
||||
|
||||
38
vendor/github.com/andygrunwald/go-jira/component.go
generated
vendored
Normal file
38
vendor/github.com/andygrunwald/go-jira/component.go
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
package jira
|
||||
|
||||
// ComponentService handles components for the JIRA instance / API.
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/software/jira/docs/api/REST/7.10.1/#api/2/component
|
||||
type ComponentService struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
// CreateComponentOptions are passed to the ComponentService.Create function to create a new JIRA component
|
||||
type CreateComponentOptions struct {
|
||||
Name string `json:"name,omitempty" structs:"name,omitempty"`
|
||||
Description string `json:"description,omitempty" structs:"description,omitempty"`
|
||||
Lead *User `json:"lead,omitempty" structs:"lead,omitempty"`
|
||||
LeadUserName string `json:"leadUserName,omitempty" structs:"leadUserName,omitempty"`
|
||||
AssigneeType string `json:"assigneeType,omitempty" structs:"assigneeType,omitempty"`
|
||||
Assignee *User `json:"assignee,omitempty" structs:"assignee,omitempty"`
|
||||
Project string `json:"project,omitempty" structs:"project,omitempty"`
|
||||
ProjectID int `json:"projectId,omitempty" structs:"projectId,omitempty"`
|
||||
}
|
||||
|
||||
// Create creates a new JIRA component based on the given options.
|
||||
func (s *ComponentService) Create(options *CreateComponentOptions) (*ProjectComponent, *Response, error) {
|
||||
apiEndpoint := "rest/api/2/component"
|
||||
req, err := s.client.NewRequest("POST", apiEndpoint, options)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
component := new(ProjectComponent)
|
||||
resp, err := s.client.Do(req, component)
|
||||
|
||||
if err != nil {
|
||||
return nil, resp, NewJiraError(resp, err)
|
||||
}
|
||||
|
||||
return component, resp, nil
|
||||
}
|
||||
18
vendor/github.com/andygrunwald/go-jira/error.go
generated
vendored
18
vendor/github.com/andygrunwald/go-jira/error.go
generated
vendored
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
@@ -28,12 +29,19 @@ func NewJiraError(resp *Response, httpError error) error {
|
||||
if err != nil {
|
||||
return errors.Wrap(err, httpError.Error())
|
||||
}
|
||||
|
||||
jerr := Error{HTTPError: httpError}
|
||||
err = json.Unmarshal(body, &jerr)
|
||||
if err != nil {
|
||||
httpError = errors.Wrap(errors.New("Could not parse JSON"), httpError.Error())
|
||||
return errors.Wrap(err, httpError.Error())
|
||||
contentType := resp.Header.Get("Content-Type")
|
||||
if strings.HasPrefix(contentType, "application/json") {
|
||||
err = json.Unmarshal(body, &jerr)
|
||||
if err != nil {
|
||||
httpError = errors.Wrap(errors.New("Could not parse JSON"), httpError.Error())
|
||||
return errors.Wrap(err, httpError.Error())
|
||||
}
|
||||
} else {
|
||||
if httpError == nil {
|
||||
return fmt.Errorf("Got Response Status %s:%s", resp.Status, string(body))
|
||||
}
|
||||
return errors.Wrap(httpError, fmt.Sprintf("%s: %s", resp.Status, string(body)))
|
||||
}
|
||||
|
||||
return &jerr
|
||||
|
||||
43
vendor/github.com/andygrunwald/go-jira/field.go
generated
vendored
Normal file
43
vendor/github.com/andygrunwald/go-jira/field.go
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
package jira
|
||||
|
||||
// FieldService handles fields for the JIRA instance / API.
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-Field
|
||||
type FieldService struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
// Field represents a field of a JIRA issue.
|
||||
type Field struct {
|
||||
ID string `json:"id,omitempty" structs:"id,omitempty"`
|
||||
Key string `json:"key,omitempty" structs:"key,omitempty"`
|
||||
Name string `json:"name,omitempty" structs:"name,omitempty"`
|
||||
Custom bool `json:"custom,omitempty" structs:"custom,omitempty"`
|
||||
Navigable bool `json:"navigable,omitempty" structs:"navigable,omitempty"`
|
||||
Searchable bool `json:"searchable,omitempty" structs:"searchable,omitempty"`
|
||||
ClauseNames []string `json:"clauseNames,omitempty" structs:"clauseNames,omitempty"`
|
||||
Schema FieldSchema `json:"schema,omitempty" structs:"schema,omitempty"`
|
||||
}
|
||||
|
||||
type FieldSchema struct {
|
||||
Type string `json:"type,omitempty" structs:"type,omitempty"`
|
||||
System string `json:"system,omitempty" structs:"system,omitempty"`
|
||||
}
|
||||
|
||||
// GetList gets all fields from JIRA
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-field-get
|
||||
func (s *FieldService) GetList() ([]Field, *Response, error) {
|
||||
apiEndpoint := "rest/api/2/field"
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
fieldList := []Field{}
|
||||
resp, err := s.client.Do(req, &fieldList)
|
||||
if err != nil {
|
||||
return nil, resp, NewJiraError(resp, err)
|
||||
}
|
||||
return fieldList, resp, nil
|
||||
}
|
||||
224
vendor/github.com/andygrunwald/go-jira/filter.go
generated
vendored
Normal file
224
vendor/github.com/andygrunwald/go-jira/filter.go
generated
vendored
Normal file
@@ -0,0 +1,224 @@
|
||||
package jira
|
||||
|
||||
import "github.com/google/go-querystring/query"
|
||||
import "fmt"
|
||||
|
||||
// FilterService handles fields for the JIRA instance / API.
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-group-Filter
|
||||
type FilterService struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
// Filter represents a Filter in Jira
|
||||
type Filter struct {
|
||||
Self string `json:"self"`
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Owner User `json:"owner"`
|
||||
Jql string `json:"jql"`
|
||||
ViewURL string `json:"viewUrl"`
|
||||
SearchURL string `json:"searchUrl"`
|
||||
Favourite bool `json:"favourite"`
|
||||
FavouritedCount int `json:"favouritedCount"`
|
||||
SharePermissions []interface{} `json:"sharePermissions"`
|
||||
Subscriptions struct {
|
||||
Size int `json:"size"`
|
||||
Items []interface{} `json:"items"`
|
||||
MaxResults int `json:"max-results"`
|
||||
StartIndex int `json:"start-index"`
|
||||
EndIndex int `json:"end-index"`
|
||||
} `json:"subscriptions"`
|
||||
}
|
||||
|
||||
// GetMyFiltersQueryOptions specifies the optional parameters for the Get My Filters method
|
||||
type GetMyFiltersQueryOptions struct {
|
||||
IncludeFavourites bool `url:"includeFavourites,omitempty"`
|
||||
Expand string `url:"expand,omitempty"`
|
||||
}
|
||||
|
||||
// FiltersList reflects a list of filters
|
||||
type FiltersList struct {
|
||||
MaxResults int `json:"maxResults" structs:"maxResults"`
|
||||
StartAt int `json:"startAt" structs:"startAt"`
|
||||
Total int `json:"total" structs:"total"`
|
||||
IsLast bool `json:"isLast" structs:"isLast"`
|
||||
Values []FiltersListItem `json:"values" structs:"values"`
|
||||
}
|
||||
|
||||
// FiltersListItem represents a Filter of FiltersList in Jira
|
||||
type FiltersListItem struct {
|
||||
Self string `json:"self"`
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Owner User `json:"owner"`
|
||||
Jql string `json:"jql"`
|
||||
ViewURL string `json:"viewUrl"`
|
||||
SearchURL string `json:"searchUrl"`
|
||||
Favourite bool `json:"favourite"`
|
||||
FavouritedCount int `json:"favouritedCount"`
|
||||
SharePermissions []interface{} `json:"sharePermissions"`
|
||||
Subscriptions []struct {
|
||||
ID int `json:"id"`
|
||||
User User `json:"user"`
|
||||
} `json:"subscriptions"`
|
||||
}
|
||||
|
||||
// FilterSearchOptions specifies the optional parameters for the Search method
|
||||
// https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-rest-api-3-filter-search-get
|
||||
type FilterSearchOptions struct {
|
||||
// String used to perform a case-insensitive partial match with name.
|
||||
FilterName string `url:"filterName,omitempty"`
|
||||
|
||||
// User account ID used to return filters with the matching owner.accountId. This parameter cannot be used with owner.
|
||||
AccountID string `url:"accountId,omitempty"`
|
||||
|
||||
// Group name used to returns filters that are shared with a group that matches sharePermissions.group.groupname.
|
||||
GroupName string `url:"groupname,omitempty"`
|
||||
|
||||
// Project ID used to returns filters that are shared with a project that matches sharePermissions.project.id.
|
||||
// Format: int64
|
||||
ProjectID int64 `url:"projectId,omitempty"`
|
||||
|
||||
// Orders the results using one of these filter properties.
|
||||
// - `description` Orders by filter `description`. Note that this ordering works independently of whether the expand to display the description field is in use.
|
||||
// - `favourite_count` Orders by `favouritedCount`.
|
||||
// - `is_favourite` Orders by `favourite`.
|
||||
// - `id` Orders by filter `id`.
|
||||
// - `name` Orders by filter `name`.
|
||||
// - `owner` Orders by `owner.accountId`.
|
||||
//
|
||||
// Default: `name`
|
||||
//
|
||||
// Valid values: id, name, description, owner, favorite_count, is_favorite, -id, -name, -description, -owner, -favorite_count, -is_favorite
|
||||
OrderBy string `url:"orderBy,omitempty"`
|
||||
|
||||
// The index of the first item to return in a page of results (page offset).
|
||||
// Default: 0, Format: int64
|
||||
StartAt int64 `url:"startAt,omitempty"`
|
||||
|
||||
// The maximum number of items to return per page. The maximum is 100.
|
||||
// Default: 50, Format: int32
|
||||
MaxResults int32 `url:"maxResults,omitempty"`
|
||||
|
||||
// Use expand to include additional information about filter in the response. This parameter accepts multiple values separated by a comma:
|
||||
// - description Returns the description of the filter.
|
||||
// - favourite Returns an indicator of whether the user has set the filter as a favorite.
|
||||
// - favouritedCount Returns a count of how many users have set this filter as a favorite.
|
||||
// - jql Returns the JQL query that the filter uses.
|
||||
// - owner Returns the owner of the filter.
|
||||
// - searchUrl Returns a URL to perform the filter's JQL query.
|
||||
// - sharePermissions Returns the share permissions defined for the filter.
|
||||
// - subscriptions Returns the users that are subscribed to the filter.
|
||||
// - viewUrl Returns a URL to view the filter.
|
||||
Expand string `url:"expand,omitempty"`
|
||||
}
|
||||
|
||||
// GetList retrieves all filters from Jira
|
||||
func (fs *FilterService) GetList() ([]*Filter, *Response, error) {
|
||||
|
||||
options := &GetQueryOptions{}
|
||||
apiEndpoint := "rest/api/2/filter"
|
||||
req, err := fs.client.NewRequest("GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if options != nil {
|
||||
q, err := query.Values(options)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
req.URL.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
filters := []*Filter{}
|
||||
resp, err := fs.client.Do(req, &filters)
|
||||
if err != nil {
|
||||
jerr := NewJiraError(resp, err)
|
||||
return nil, resp, jerr
|
||||
}
|
||||
return filters, resp, err
|
||||
}
|
||||
|
||||
// GetFavouriteList retrieves the user's favourited filters from Jira
|
||||
func (fs *FilterService) GetFavouriteList() ([]*Filter, *Response, error) {
|
||||
apiEndpoint := "rest/api/2/filter/favourite"
|
||||
req, err := fs.client.NewRequest("GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
filters := []*Filter{}
|
||||
resp, err := fs.client.Do(req, &filters)
|
||||
if err != nil {
|
||||
jerr := NewJiraError(resp, err)
|
||||
return nil, resp, jerr
|
||||
}
|
||||
return filters, resp, err
|
||||
}
|
||||
|
||||
// Get retrieves a single Filter from Jira
|
||||
func (fs *FilterService) Get(filterID int) (*Filter, *Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("rest/api/2/filter/%d", filterID)
|
||||
req, err := fs.client.NewRequest("GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
filter := new(Filter)
|
||||
resp, err := fs.client.Do(req, filter)
|
||||
if err != nil {
|
||||
jerr := NewJiraError(resp, err)
|
||||
return nil, resp, jerr
|
||||
}
|
||||
|
||||
return filter, resp, err
|
||||
}
|
||||
|
||||
// GetMyFilters retrieves the my Filters.
|
||||
//
|
||||
// https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-rest-api-3-filter-my-get
|
||||
func (fs *FilterService) GetMyFilters(opts *GetMyFiltersQueryOptions) ([]*Filter, *Response, error) {
|
||||
apiEndpoint := "rest/api/3/filter/my"
|
||||
url, err := addOptions(apiEndpoint, opts)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
req, err := fs.client.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
filters := []*Filter{}
|
||||
resp, err := fs.client.Do(req, &filters)
|
||||
if err != nil {
|
||||
jerr := NewJiraError(resp, err)
|
||||
return nil, resp, jerr
|
||||
}
|
||||
return filters, resp, nil
|
||||
}
|
||||
|
||||
// Search will search for filter according to the search options
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-rest-api-3-filter-search-get
|
||||
func (fs *FilterService) Search(opt *FilterSearchOptions) (*FiltersList, *Response, error) {
|
||||
apiEndpoint := "rest/api/3/filter/search"
|
||||
url, err := addOptions(apiEndpoint, opt)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
req, err := fs.client.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
filters := new(FiltersList)
|
||||
resp, err := fs.client.Do(req, filters)
|
||||
if err != nil {
|
||||
jerr := NewJiraError(resp, err)
|
||||
return nil, resp, jerr
|
||||
}
|
||||
|
||||
return filters, resp, err
|
||||
}
|
||||
13
vendor/github.com/andygrunwald/go-jira/go.mod
generated
vendored
Normal file
13
vendor/github.com/andygrunwald/go-jira/go.mod
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
module github.com/andygrunwald/go-jira
|
||||
|
||||
go 1.12
|
||||
|
||||
require (
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||
github.com/fatih/structs v1.0.0
|
||||
github.com/google/go-cmp v0.3.0
|
||||
github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135
|
||||
github.com/pkg/errors v0.8.0
|
||||
github.com/trivago/tgo v1.0.1
|
||||
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734
|
||||
)
|
||||
20
vendor/github.com/andygrunwald/go-jira/go.sum
generated
vendored
Normal file
20
vendor/github.com/andygrunwald/go-jira/go.sum
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/fatih/structs v1.0.0 h1:BrX964Rv5uQ3wwS+KRUAJCBBw5PQmgJfJ6v4yly5QwU=
|
||||
github.com/fatih/structs v1.0.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135 h1:zLTLjkaOFEFIOxY5BWLFLwh+cL8vOBW4XJ2aqLE/Tf0=
|
||||
github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/trivago/tgo v1.0.1 h1:bxatjJIXNIpV18bucU4Uk/LaoxvxuOlp/oowRHyncLQ=
|
||||
github.com/trivago/tgo v1.0.1/go.mod h1:w4dpD+3tzNIIiIfkWWa85w5/B77tlvdZckQ+6PkFnhc=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734 h1:p/H982KKEjUnLJkM3tt/LemDnOc1GiZL5FCVlORJ5zo=
|
||||
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
5
vendor/github.com/andygrunwald/go-jira/group.go
generated
vendored
5
vendor/github.com/andygrunwald/go-jira/group.go
generated
vendored
@@ -43,12 +43,15 @@ type GroupMember struct {
|
||||
Self string `json:"self,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Key string `json:"key,omitempty"`
|
||||
AccountID string `json:"accountId,omitempty"`
|
||||
EmailAddress string `json:"emailAddress,omitempty"`
|
||||
DisplayName string `json:"displayName,omitempty"`
|
||||
Active bool `json:"active,omitempty"`
|
||||
TimeZone string `json:"timeZone,omitempty"`
|
||||
AccountType string `json:"accountType,omitempty"`
|
||||
}
|
||||
|
||||
// GroupSearchOptions specifies the optional parameters for the Get Group methods
|
||||
type GroupSearchOptions struct {
|
||||
StartAt int
|
||||
MaxResults int
|
||||
@@ -78,7 +81,7 @@ func (s *GroupService) Get(name string) ([]GroupMember, *Response, error) {
|
||||
return group.Members, resp, nil
|
||||
}
|
||||
|
||||
// Get returns a paginated list of members of the specified group and its subgroups.
|
||||
// GetWithOptions returns a paginated list of members of the specified group and its subgroups.
|
||||
// Users in the page are ordered by user names.
|
||||
// User of this resource is required to have sysadmin or admin permissions.
|
||||
//
|
||||
|
||||
446
vendor/github.com/andygrunwald/go-jira/issue.go
generated
vendored
446
vendor/github.com/andygrunwald/go-jira/issue.go
generated
vendored
File diff suppressed because it is too large
Load Diff
111
vendor/github.com/andygrunwald/go-jira/issuelinktype.go
generated
vendored
Normal file
111
vendor/github.com/andygrunwald/go-jira/issuelinktype.go
generated
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
package jira
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
// IssueLinkTypeService handles issue link types for the JIRA instance / API.
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-group-Issue-link-types
|
||||
type IssueLinkTypeService struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
// GetList gets all of the issue link types from JIRA.
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issueLinkType-get
|
||||
func (s *IssueLinkTypeService) GetList() ([]IssueLinkType, *Response, error) {
|
||||
apiEndpoint := "rest/api/2/issueLinkType"
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
linkTypeList := []IssueLinkType{}
|
||||
resp, err := s.client.Do(req, &linkTypeList)
|
||||
if err != nil {
|
||||
return nil, resp, NewJiraError(resp, err)
|
||||
}
|
||||
return linkTypeList, resp, nil
|
||||
}
|
||||
|
||||
// Get gets info of a specific issue link type from JIRA.
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issueLinkType-issueLinkTypeId-get
|
||||
func (s *IssueLinkTypeService) Get(ID string) (*IssueLinkType, *Response, error) {
|
||||
apiEndPoint := fmt.Sprintf("rest/api/2/issueLinkType/%s", ID)
|
||||
req, err := s.client.NewRequest("GET", apiEndPoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
linkType := new(IssueLinkType)
|
||||
resp, err := s.client.Do(req, linkType)
|
||||
if err != nil {
|
||||
return nil, resp, NewJiraError(resp, err)
|
||||
}
|
||||
return linkType, resp, nil
|
||||
}
|
||||
|
||||
// Create creates an issue link type in JIRA.
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issueLinkType-post
|
||||
func (s *IssueLinkTypeService) Create(linkType *IssueLinkType) (*IssueLinkType, *Response, error) {
|
||||
apiEndpoint := "/rest/api/2/issueLinkType"
|
||||
req, err := s.client.NewRequest("POST", apiEndpoint, linkType)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
resp, err := s.client.Do(req, nil)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
|
||||
responseLinkType := new(IssueLinkType)
|
||||
defer resp.Body.Close()
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
e := fmt.Errorf("Could not read the returned data")
|
||||
return nil, resp, NewJiraError(resp, e)
|
||||
}
|
||||
err = json.Unmarshal(data, responseLinkType)
|
||||
if err != nil {
|
||||
e := fmt.Errorf("Could no unmarshal the data into struct")
|
||||
return nil, resp, NewJiraError(resp, e)
|
||||
}
|
||||
return linkType, resp, nil
|
||||
}
|
||||
|
||||
// Update updates an issue link type. The issue is found by key.
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issueLinkType-issueLinkTypeId-put
|
||||
func (s *IssueLinkTypeService) Update(linkType *IssueLinkType) (*IssueLinkType, *Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("rest/api/2/issueLinkType/%s", linkType.ID)
|
||||
req, err := s.client.NewRequest("PUT", apiEndpoint, linkType)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
resp, err := s.client.Do(req, nil)
|
||||
if err != nil {
|
||||
return nil, resp, NewJiraError(resp, err)
|
||||
}
|
||||
ret := *linkType
|
||||
return &ret, resp, nil
|
||||
}
|
||||
|
||||
// Delete deletes an issue link type based on provided ID.
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issueLinkType-issueLinkTypeId-delete
|
||||
func (s *IssueLinkTypeService) Delete(ID string) (*Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("rest/api/2/issueLinkType/%s", ID)
|
||||
req, err := s.client.NewRequest("DELETE", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := s.client.Do(req, nil)
|
||||
return resp, err
|
||||
}
|
||||
146
vendor/github.com/andygrunwald/go-jira/jira.go
generated
vendored
146
vendor/github.com/andygrunwald/go-jira/jira.go
generated
vendored
@@ -2,38 +2,59 @@ package jira
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"github.com/google/go-querystring/query"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// httpClient defines an interface for an http.Client implementation so that alternative
|
||||
// http Clients can be passed in for making requests
|
||||
type httpClient interface {
|
||||
Do(request *http.Request) (response *http.Response, err error)
|
||||
}
|
||||
|
||||
// A Client manages communication with the JIRA API.
|
||||
type Client struct {
|
||||
// HTTP client used to communicate with the API.
|
||||
client *http.Client
|
||||
client httpClient
|
||||
|
||||
// Base URL for API requests.
|
||||
baseURL *url.URL
|
||||
|
||||
// Session storage if the user authentificate with a Session cookie
|
||||
// Session storage if the user authenticates with a Session cookie
|
||||
session *Session
|
||||
|
||||
// Services used for talking to different parts of the JIRA API.
|
||||
Authentication *AuthenticationService
|
||||
Issue *IssueService
|
||||
Project *ProjectService
|
||||
Board *BoardService
|
||||
Sprint *SprintService
|
||||
User *UserService
|
||||
Group *GroupService
|
||||
Version *VersionService
|
||||
Authentication *AuthenticationService
|
||||
Issue *IssueService
|
||||
Project *ProjectService
|
||||
Board *BoardService
|
||||
Sprint *SprintService
|
||||
User *UserService
|
||||
Group *GroupService
|
||||
Version *VersionService
|
||||
Priority *PriorityService
|
||||
Field *FieldService
|
||||
Component *ComponentService
|
||||
Resolution *ResolutionService
|
||||
StatusCategory *StatusCategoryService
|
||||
Filter *FilterService
|
||||
Role *RoleService
|
||||
PermissionScheme *PermissionSchemeService
|
||||
Status *StatusService
|
||||
IssueLinkType *IssueLinkTypeService
|
||||
}
|
||||
|
||||
// NewClient returns a new JIRA API client.
|
||||
@@ -43,11 +64,16 @@ type Client struct {
|
||||
// As an alternative you can use Session Cookie based authentication provided by this package as well.
|
||||
// See https://docs.atlassian.com/jira/REST/latest/#authentication
|
||||
// baseURL is the HTTP endpoint of your JIRA instance and should always be specified with a trailing slash.
|
||||
func NewClient(httpClient *http.Client, baseURL string) (*Client, error) {
|
||||
func NewClient(httpClient httpClient, baseURL string) (*Client, error) {
|
||||
if httpClient == nil {
|
||||
httpClient = http.DefaultClient
|
||||
}
|
||||
|
||||
// ensure the baseURL contains a trailing slash so that all paths are preserved in later calls
|
||||
if !strings.HasSuffix(baseURL, "/") {
|
||||
baseURL += "/"
|
||||
}
|
||||
|
||||
parsedBaseURL, err := url.Parse(baseURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -65,19 +91,30 @@ func NewClient(httpClient *http.Client, baseURL string) (*Client, error) {
|
||||
c.User = &UserService{client: c}
|
||||
c.Group = &GroupService{client: c}
|
||||
c.Version = &VersionService{client: c}
|
||||
c.Priority = &PriorityService{client: c}
|
||||
c.Field = &FieldService{client: c}
|
||||
c.Component = &ComponentService{client: c}
|
||||
c.Resolution = &ResolutionService{client: c}
|
||||
c.StatusCategory = &StatusCategoryService{client: c}
|
||||
c.Filter = &FilterService{client: c}
|
||||
c.Role = &RoleService{client: c}
|
||||
c.PermissionScheme = &PermissionSchemeService{client: c}
|
||||
c.Status = &StatusService{client: c}
|
||||
c.IssueLinkType = &IssueLinkTypeService{client: c}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// NewRawRequest creates an API request.
|
||||
// A relative URL can be provided in urlStr, in which case it is resolved relative to the baseURL of the Client.
|
||||
// Relative URLs should always be specified without a preceding slash.
|
||||
// Allows using an optional native io.Reader for sourcing the request body.
|
||||
func (c *Client) NewRawRequest(method, urlStr string, body io.Reader) (*http.Request, error) {
|
||||
rel, err := url.Parse(urlStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Relative URLs should be specified without a preceding slash since baseURL will have the trailing slash
|
||||
rel.Path = strings.TrimLeft(rel.Path, "/")
|
||||
|
||||
u := c.baseURL.ResolveReference(rel)
|
||||
|
||||
@@ -108,13 +145,14 @@ func (c *Client) NewRawRequest(method, urlStr string, body io.Reader) (*http.Req
|
||||
|
||||
// NewRequest creates an API request.
|
||||
// A relative URL can be provided in urlStr, in which case it is resolved relative to the baseURL of the Client.
|
||||
// Relative URLs should always be specified without a preceding slash.
|
||||
// If specified, the value pointed to by body is JSON encoded and included as the request body.
|
||||
func (c *Client) NewRequest(method, urlStr string, body interface{}) (*http.Request, error) {
|
||||
rel, err := url.Parse(urlStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Relative URLs should be specified without a preceding slash since baseURL will have the trailing slash
|
||||
rel.Path = strings.TrimLeft(rel.Path, "/")
|
||||
|
||||
u := c.baseURL.ResolveReference(rel)
|
||||
|
||||
@@ -176,13 +214,14 @@ func addOptions(s string, opt interface{}) (string, error) {
|
||||
|
||||
// NewMultiPartRequest creates an API request including a multi-part file.
|
||||
// A relative URL can be provided in urlStr, in which case it is resolved relative to the baseURL of the Client.
|
||||
// Relative URLs should always be specified without a preceding slash.
|
||||
// If specified, the value pointed to by buf is a multipart form.
|
||||
func (c *Client) NewMultiPartRequest(method, urlStr string, buf *bytes.Buffer) (*http.Request, error) {
|
||||
rel, err := url.Parse(urlStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Relative URLs should be specified without a preceding slash since baseURL will have the trailing slash
|
||||
rel.Path = strings.TrimLeft(rel.Path, "/")
|
||||
|
||||
u := c.baseURL.ResolveReference(rel)
|
||||
|
||||
@@ -327,7 +366,7 @@ func (t *BasicAuthTransport) transport() http.RoundTripper {
|
||||
// CookieAuthTransport is an http.RoundTripper that authenticates all requests
|
||||
// using Jira's cookie-based authentication.
|
||||
//
|
||||
// Note that it is generally preferrable to use HTTP BASIC authentication with the REST API.
|
||||
// Note that it is generally preferable to use HTTP BASIC authentication with the REST API.
|
||||
// However, this resource may be used to mimic the behaviour of JIRA's log-in page (e.g. to display log-in errors to a user).
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#auth/1/session
|
||||
@@ -356,7 +395,10 @@ func (t *CookieAuthTransport) RoundTrip(req *http.Request) (*http.Response, erro
|
||||
|
||||
req2 := cloneRequest(req) // per RoundTripper contract
|
||||
for _, cookie := range t.SessionObject {
|
||||
req2.AddCookie(cookie)
|
||||
// Don't add an empty value cookie to the request
|
||||
if cookie.Value != "" {
|
||||
req2.AddCookie(cookie)
|
||||
}
|
||||
}
|
||||
|
||||
return t.transport().RoundTrip(req2)
|
||||
@@ -417,6 +459,78 @@ func (t *CookieAuthTransport) transport() http.RoundTripper {
|
||||
return http.DefaultTransport
|
||||
}
|
||||
|
||||
// JWTAuthTransport is an http.RoundTripper that authenticates all requests
|
||||
// using Jira's JWT based authentication.
|
||||
//
|
||||
// NOTE: this form of auth should be used by add-ons installed from the Atlassian marketplace.
|
||||
//
|
||||
// JIRA docs: https://developer.atlassian.com/cloud/jira/platform/understanding-jwt
|
||||
// Examples in other languages:
|
||||
// https://bitbucket.org/atlassian/atlassian-jwt-ruby/src/d44a8e7a4649e4f23edaa784402655fda7c816ea/lib/atlassian/jwt.rb
|
||||
// https://bitbucket.org/atlassian/atlassian-jwt-py/src/master/atlassian_jwt/url_utils.py
|
||||
type JWTAuthTransport struct {
|
||||
Secret []byte
|
||||
Issuer string
|
||||
|
||||
// Transport is the underlying HTTP transport to use when making requests.
|
||||
// It will default to http.DefaultTransport if nil.
|
||||
Transport http.RoundTripper
|
||||
}
|
||||
|
||||
func (t *JWTAuthTransport) Client() *http.Client {
|
||||
return &http.Client{Transport: t}
|
||||
}
|
||||
|
||||
func (t *JWTAuthTransport) transport() http.RoundTripper {
|
||||
if t.Transport != nil {
|
||||
return t.Transport
|
||||
}
|
||||
return http.DefaultTransport
|
||||
}
|
||||
|
||||
// RoundTrip adds the session object to the request.
|
||||
func (t *JWTAuthTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
req2 := cloneRequest(req) // per RoundTripper contract
|
||||
exp := time.Duration(59) * time.Second
|
||||
qsh := t.createQueryStringHash(req.Method, req2.URL)
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
|
||||
"iss": t.Issuer,
|
||||
"iat": time.Now().Unix(),
|
||||
"exp": time.Now().Add(exp).Unix(),
|
||||
"qsh": qsh,
|
||||
})
|
||||
|
||||
jwtStr, err := token.SignedString(t.Secret)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "jwtAuth: error signing JWT")
|
||||
}
|
||||
|
||||
req2.Header.Set("Authorization", fmt.Sprintf("JWT %s", jwtStr))
|
||||
return t.transport().RoundTrip(req2)
|
||||
}
|
||||
|
||||
func (t *JWTAuthTransport) createQueryStringHash(httpMethod string, jiraURL *url.URL) string {
|
||||
canonicalRequest := t.canonicalizeRequest(httpMethod, jiraURL)
|
||||
h := sha256.Sum256([]byte(canonicalRequest))
|
||||
return hex.EncodeToString(h[:])
|
||||
}
|
||||
|
||||
func (t *JWTAuthTransport) canonicalizeRequest(httpMethod string, jiraURL *url.URL) string {
|
||||
path := "/" + strings.Replace(strings.Trim(jiraURL.Path, "/"), "&", "%26", -1)
|
||||
|
||||
var canonicalQueryString []string
|
||||
for k, v := range jiraURL.Query() {
|
||||
if k == "jwt" {
|
||||
continue
|
||||
}
|
||||
param := url.QueryEscape(k)
|
||||
value := url.QueryEscape(strings.Join(v, ""))
|
||||
canonicalQueryString = append(canonicalQueryString, strings.Replace(strings.Join([]string{param, value}, "="), "+", "%20", -1))
|
||||
}
|
||||
sort.Strings(canonicalQueryString)
|
||||
return fmt.Sprintf("%s&%s&%s", strings.ToUpper(httpMethod), path, strings.Join(canonicalQueryString, "&"))
|
||||
}
|
||||
|
||||
// cloneRequest returns a clone of the provided *http.Request.
|
||||
// The clone is a shallow copy of the struct and its Header map.
|
||||
func cloneRequest(r *http.Request) *http.Request {
|
||||
|
||||
69
vendor/github.com/andygrunwald/go-jira/permissionscheme.go
generated
vendored
Normal file
69
vendor/github.com/andygrunwald/go-jira/permissionscheme.go
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
package jira
|
||||
|
||||
import "fmt"
|
||||
|
||||
// PermissionSchemeService handles permissionschemes for the JIRA instance / API.
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-group-Permissionscheme
|
||||
type PermissionSchemeService struct {
|
||||
client *Client
|
||||
}
|
||||
type PermissionSchemes struct {
|
||||
PermissionSchemes []PermissionScheme `json:"permissionSchemes" structs:"permissionSchemes"`
|
||||
}
|
||||
|
||||
type Permission struct {
|
||||
ID int `json:"id" structs:"id"`
|
||||
Self string `json:"expand" structs:"expand"`
|
||||
Holder Holder `json:"holder" structs:"holder"`
|
||||
Name string `json:"permission" structs:"permission"`
|
||||
}
|
||||
|
||||
type Holder struct {
|
||||
Type string `json:"type" structs:"type"`
|
||||
Parameter string `json:"parameter" structs:"parameter"`
|
||||
Expand string `json:"expand" structs:"expand"`
|
||||
}
|
||||
|
||||
// GetList returns a list of all permission schemes
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-api-3-permissionscheme-get
|
||||
func (s *PermissionSchemeService) GetList() (*PermissionSchemes, *Response, error) {
|
||||
apiEndpoint := "/rest/api/3/permissionscheme"
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
pss := new(PermissionSchemes)
|
||||
resp, err := s.client.Do(req, &pss)
|
||||
if err != nil {
|
||||
jerr := NewJiraError(resp, err)
|
||||
return nil, resp, jerr
|
||||
}
|
||||
|
||||
return pss, resp, nil
|
||||
}
|
||||
|
||||
// Get returns a full representation of the permission scheme for the schemeID
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-api-3-permissionscheme-schemeId-get
|
||||
func (s *PermissionSchemeService) Get(schemeID int) (*PermissionScheme, *Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("/rest/api/3/permissionscheme/%d", schemeID)
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
ps := new(PermissionScheme)
|
||||
resp, err := s.client.Do(req, ps)
|
||||
if err != nil {
|
||||
jerr := NewJiraError(resp, err)
|
||||
return nil, resp, jerr
|
||||
}
|
||||
if ps.Self == "" {
|
||||
return nil, resp, fmt.Errorf("No permissionscheme with ID %d found", schemeID)
|
||||
}
|
||||
|
||||
return ps, resp, nil
|
||||
}
|
||||
37
vendor/github.com/andygrunwald/go-jira/priority.go
generated
vendored
Normal file
37
vendor/github.com/andygrunwald/go-jira/priority.go
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
package jira
|
||||
|
||||
// PriorityService handles priorities for the JIRA instance / API.
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-Priority
|
||||
type PriorityService struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
// Priority represents a priority of a JIRA issue.
|
||||
// Typical types are "Normal", "Moderate", "Urgent", ...
|
||||
type Priority struct {
|
||||
Self string `json:"self,omitempty" structs:"self,omitempty"`
|
||||
IconURL string `json:"iconUrl,omitempty" structs:"iconUrl,omitempty"`
|
||||
Name string `json:"name,omitempty" structs:"name,omitempty"`
|
||||
ID string `json:"id,omitempty" structs:"id,omitempty"`
|
||||
StatusColor string `json:"statusColor,omitempty" structs:"statusColor,omitempty"`
|
||||
Description string `json:"description,omitempty" structs:"description,omitempty"`
|
||||
}
|
||||
|
||||
// GetList gets all priorities from JIRA
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-priority-get
|
||||
func (s *PriorityService) GetList() ([]Priority, *Response, error) {
|
||||
apiEndpoint := "rest/api/2/priority"
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
priorityList := []Priority{}
|
||||
resp, err := s.client.Do(req, &priorityList)
|
||||
if err != nil {
|
||||
return nil, resp, NewJiraError(resp, err)
|
||||
}
|
||||
return priorityList, resp, nil
|
||||
}
|
||||
45
vendor/github.com/andygrunwald/go-jira/project.go
generated
vendored
45
vendor/github.com/andygrunwald/go-jira/project.go
generated
vendored
@@ -36,24 +36,22 @@ type ProjectCategory struct {
|
||||
|
||||
// Project represents a JIRA Project.
|
||||
type Project struct {
|
||||
Expand string `json:"expand,omitempty" structs:"expand,omitempty"`
|
||||
Self string `json:"self,omitempty" structs:"self,omitempty"`
|
||||
ID string `json:"id,omitempty" structs:"id,omitempty"`
|
||||
Key string `json:"key,omitempty" structs:"key,omitempty"`
|
||||
Description string `json:"description,omitempty" structs:"description,omitempty"`
|
||||
Lead User `json:"lead,omitempty" structs:"lead,omitempty"`
|
||||
Components []ProjectComponent `json:"components,omitempty" structs:"components,omitempty"`
|
||||
IssueTypes []IssueType `json:"issueTypes,omitempty" structs:"issueTypes,omitempty"`
|
||||
URL string `json:"url,omitempty" structs:"url,omitempty"`
|
||||
Email string `json:"email,omitempty" structs:"email,omitempty"`
|
||||
AssigneeType string `json:"assigneeType,omitempty" structs:"assigneeType,omitempty"`
|
||||
Versions []Version `json:"versions,omitempty" structs:"versions,omitempty"`
|
||||
Name string `json:"name,omitempty" structs:"name,omitempty"`
|
||||
Roles struct {
|
||||
Developers string `json:"Developers,omitempty" structs:"Developers,omitempty"`
|
||||
} `json:"roles,omitempty" structs:"roles,omitempty"`
|
||||
AvatarUrls AvatarUrls `json:"avatarUrls,omitempty" structs:"avatarUrls,omitempty"`
|
||||
ProjectCategory ProjectCategory `json:"projectCategory,omitempty" structs:"projectCategory,omitempty"`
|
||||
Expand string `json:"expand,omitempty" structs:"expand,omitempty"`
|
||||
Self string `json:"self,omitempty" structs:"self,omitempty"`
|
||||
ID string `json:"id,omitempty" structs:"id,omitempty"`
|
||||
Key string `json:"key,omitempty" structs:"key,omitempty"`
|
||||
Description string `json:"description,omitempty" structs:"description,omitempty"`
|
||||
Lead User `json:"lead,omitempty" structs:"lead,omitempty"`
|
||||
Components []ProjectComponent `json:"components,omitempty" structs:"components,omitempty"`
|
||||
IssueTypes []IssueType `json:"issueTypes,omitempty" structs:"issueTypes,omitempty"`
|
||||
URL string `json:"url,omitempty" structs:"url,omitempty"`
|
||||
Email string `json:"email,omitempty" structs:"email,omitempty"`
|
||||
AssigneeType string `json:"assigneeType,omitempty" structs:"assigneeType,omitempty"`
|
||||
Versions []Version `json:"versions,omitempty" structs:"versions,omitempty"`
|
||||
Name string `json:"name,omitempty" structs:"name,omitempty"`
|
||||
Roles map[string]string `json:"roles,omitempty" structs:"roles,omitempty"`
|
||||
AvatarUrls AvatarUrls `json:"avatarUrls,omitempty" structs:"avatarUrls,omitempty"`
|
||||
ProjectCategory ProjectCategory `json:"projectCategory,omitempty" structs:"projectCategory,omitempty"`
|
||||
}
|
||||
|
||||
// ProjectComponent represents a single component of a project
|
||||
@@ -74,11 +72,12 @@ type ProjectComponent struct {
|
||||
|
||||
// PermissionScheme represents the permission scheme for the project
|
||||
type PermissionScheme struct {
|
||||
Expand string `json:"expand" structs:"expand,omitempty"`
|
||||
Self string `json:"self" structs:"self,omitempty"`
|
||||
ID int `json:"id" structs:"id,omitempty"`
|
||||
Name string `json:"name" structs:"name,omitempty"`
|
||||
Description string `json:"description" structs:"description,omitempty"`
|
||||
Expand string `json:"expand" structs:"expand,omitempty"`
|
||||
Self string `json:"self" structs:"self,omitempty"`
|
||||
ID int `json:"id" structs:"id,omitempty"`
|
||||
Name string `json:"name" structs:"name,omitempty"`
|
||||
Description string `json:"description" structs:"description,omitempty"`
|
||||
Permissions []Permission `json:"permissions" structs:"permissions,omitempty"`
|
||||
}
|
||||
|
||||
// GetList gets all projects form JIRA
|
||||
|
||||
35
vendor/github.com/andygrunwald/go-jira/resolution.go
generated
vendored
Normal file
35
vendor/github.com/andygrunwald/go-jira/resolution.go
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
package jira
|
||||
|
||||
// ResolutionService handles resolutions for the JIRA instance / API.
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-Resolution
|
||||
type ResolutionService struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
// Resolution represents a resolution of a JIRA issue.
|
||||
// Typical types are "Fixed", "Suspended", "Won't Fix", ...
|
||||
type Resolution struct {
|
||||
Self string `json:"self" structs:"self"`
|
||||
ID string `json:"id" structs:"id"`
|
||||
Description string `json:"description" structs:"description"`
|
||||
Name string `json:"name" structs:"name"`
|
||||
}
|
||||
|
||||
// GetList gets all resolutions from JIRA
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-resolution-get
|
||||
func (s *ResolutionService) GetList() ([]Resolution, *Response, error) {
|
||||
apiEndpoint := "rest/api/2/resolution"
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
resolutionList := []Resolution{}
|
||||
resp, err := s.client.Do(req, &resolutionList)
|
||||
if err != nil {
|
||||
return nil, resp, NewJiraError(resp, err)
|
||||
}
|
||||
return resolutionList, resp, nil
|
||||
}
|
||||
76
vendor/github.com/andygrunwald/go-jira/role.go
generated
vendored
Normal file
76
vendor/github.com/andygrunwald/go-jira/role.go
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
package jira
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// RoleService handles roles for the JIRA instance / API.
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-group-Role
|
||||
type RoleService struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
// Role represents a JIRA product role
|
||||
type Role struct {
|
||||
Self string `json:"self" structs:"self"`
|
||||
Name string `json:"name" structs:"name"`
|
||||
ID int `json:"id" structs:"id"`
|
||||
Description string `json:"description" structs:"description"`
|
||||
Actors []*Actor `json:"actors" structs:"actors"`
|
||||
}
|
||||
|
||||
// Actor represents a JIRA actor
|
||||
type Actor struct {
|
||||
ID int `json:"id" structs:"id"`
|
||||
DisplayName string `json:"displayName" structs:"displayName"`
|
||||
Type string `json:"type" structs:"type"`
|
||||
Name string `json:"name" structs:"name"`
|
||||
AvatarURL string `json:"avatarUrl" structs:"avatarUrl"`
|
||||
ActorUser *ActorUser `json:"actorUser" structs:"actoruser"`
|
||||
}
|
||||
|
||||
// ActorUser contains the account id of the actor/user
|
||||
type ActorUser struct {
|
||||
AccountID string `json:"accountId" structs:"accountId"`
|
||||
}
|
||||
|
||||
// GetList returns a list of all available project roles
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-api-3-role-get
|
||||
func (s *RoleService) GetList() (*[]Role, *Response, error) {
|
||||
apiEndpoint := "rest/api/3/role"
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
roles := new([]Role)
|
||||
resp, err := s.client.Do(req, roles)
|
||||
if err != nil {
|
||||
jerr := NewJiraError(resp, err)
|
||||
return nil, resp, jerr
|
||||
}
|
||||
return roles, resp, err
|
||||
}
|
||||
|
||||
// Get retreives a single Role from Jira
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-api-3-role-id-get
|
||||
func (s *RoleService) Get(roleID int) (*Role, *Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("rest/api/3/role/%d", roleID)
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
role := new(Role)
|
||||
resp, err := s.client.Do(req, role)
|
||||
if err != nil {
|
||||
jerr := NewJiraError(resp, err)
|
||||
return nil, resp, jerr
|
||||
}
|
||||
if role.Self == "" {
|
||||
return nil, resp, fmt.Errorf("No role with ID %d found", roleID)
|
||||
}
|
||||
|
||||
return role, resp, err
|
||||
}
|
||||
3
vendor/github.com/andygrunwald/go-jira/sprint.go
generated
vendored
3
vendor/github.com/andygrunwald/go-jira/sprint.go
generated
vendored
@@ -2,6 +2,7 @@ package jira
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/google/go-querystring/query"
|
||||
)
|
||||
|
||||
@@ -67,7 +68,7 @@ func (s *SprintService) GetIssuesForSprint(sprintID int) ([]Issue, *Response, er
|
||||
return result.Issues, resp, err
|
||||
}
|
||||
|
||||
// Get returns a full representation of the issue for the given issue key.
|
||||
// GetIssue returns a full representation of the issue for the given issue key.
|
||||
// JIRA will attempt to identify the issue by the issueIdOrKey path parameter.
|
||||
// This can be an issue id, or an issue key.
|
||||
// If the issue cannot be found via an exact match, JIRA will also look for the issue in a case-insensitive way, or by looking to see if the issue was moved.
|
||||
|
||||
40
vendor/github.com/andygrunwald/go-jira/status.go
generated
vendored
Normal file
40
vendor/github.com/andygrunwald/go-jira/status.go
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
package jira
|
||||
|
||||
// StatusService handles staties for the JIRA instance / API.
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-group-Workflow-statuses
|
||||
type StatusService struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
// Status represents the current status of a JIRA issue.
|
||||
// Typical status are "Open", "In Progress", "Closed", ...
|
||||
// Status can be user defined in every JIRA instance.
|
||||
type Status struct {
|
||||
Self string `json:"self" structs:"self"`
|
||||
Description string `json:"description" structs:"description"`
|
||||
IconURL string `json:"iconUrl" structs:"iconUrl"`
|
||||
Name string `json:"name" structs:"name"`
|
||||
ID string `json:"id" structs:"id"`
|
||||
StatusCategory StatusCategory `json:"statusCategory" structs:"statusCategory"`
|
||||
}
|
||||
|
||||
// GetAllStatuses returns a list of all statuses associated with workflows.
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-status-get
|
||||
func (s *StatusService) GetAllStatuses() ([]Status, *Response, error) {
|
||||
apiEndpoint := "rest/api/2/status"
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
statusList := []Status{}
|
||||
resp, err := s.client.Do(req, &statusList)
|
||||
if err != nil {
|
||||
return nil, resp, NewJiraError(resp, err)
|
||||
}
|
||||
|
||||
return statusList, resp, nil
|
||||
}
|
||||
44
vendor/github.com/andygrunwald/go-jira/statuscategory.go
generated
vendored
Normal file
44
vendor/github.com/andygrunwald/go-jira/statuscategory.go
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
package jira
|
||||
|
||||
// StatusCategoryService handles status categories for the JIRA instance / API.
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-Statuscategory
|
||||
type StatusCategoryService struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
// StatusCategory represents the category a status belongs to.
|
||||
// Those categories can be user defined in every JIRA instance.
|
||||
type StatusCategory struct {
|
||||
Self string `json:"self" structs:"self"`
|
||||
ID int `json:"id" structs:"id"`
|
||||
Name string `json:"name" structs:"name"`
|
||||
Key string `json:"key" structs:"key"`
|
||||
ColorName string `json:"colorName" structs:"colorName"`
|
||||
}
|
||||
|
||||
// These constants are the keys of the default JIRA status categories
|
||||
const (
|
||||
StatusCategoryComplete = "done"
|
||||
StatusCategoryInProgress = "indeterminate"
|
||||
StatusCategoryToDo = "new"
|
||||
StatusCategoryUndefined = "undefined"
|
||||
)
|
||||
|
||||
// GetList gets all status categories from JIRA
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-statuscategory-get
|
||||
func (s *StatusCategoryService) GetList() ([]StatusCategory, *Response, error) {
|
||||
apiEndpoint := "rest/api/2/statuscategory"
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
statusCategoryList := []StatusCategory{}
|
||||
resp, err := s.client.Do(req, &statusCategoryList)
|
||||
if err != nil {
|
||||
return nil, resp, NewJiraError(resp, err)
|
||||
}
|
||||
return statusCategoryList, resp, nil
|
||||
}
|
||||
104
vendor/github.com/andygrunwald/go-jira/user.go
generated
vendored
104
vendor/github.com/andygrunwald/go-jira/user.go
generated
vendored
@@ -15,15 +15,20 @@ type UserService struct {
|
||||
|
||||
// User represents a JIRA user.
|
||||
type User struct {
|
||||
Self string `json:"self,omitempty" structs:"self,omitempty"`
|
||||
Self string `json:"self,omitempty" structs:"self,omitempty"`
|
||||
AccountID string `json:"accountId,omitempty" structs:"accountId,omitempty"`
|
||||
AccountType string `json:"accountType,omitempty" structs:"accountType,omitempty"`
|
||||
// TODO: name & key are deprecated, see:
|
||||
// https://developer.atlassian.com/cloud/jira/platform/api-changes-for-user-privacy-announcement/
|
||||
Name string `json:"name,omitempty" structs:"name,omitempty"`
|
||||
Password string `json:"-"`
|
||||
Key string `json:"key,omitempty" structs:"key,omitempty"`
|
||||
Password string `json:"-"`
|
||||
EmailAddress string `json:"emailAddress,omitempty" structs:"emailAddress,omitempty"`
|
||||
AvatarUrls AvatarUrls `json:"avatarUrls,omitempty" structs:"avatarUrls,omitempty"`
|
||||
DisplayName string `json:"displayName,omitempty" structs:"displayName,omitempty"`
|
||||
Active bool `json:"active,omitempty" structs:"active,omitempty"`
|
||||
TimeZone string `json:"timeZone,omitempty" structs:"timeZone,omitempty"`
|
||||
Locale string `json:"locale,omitempty" structs:"locale,omitempty"`
|
||||
ApplicationKeys []string `json:"applicationKeys,omitempty" structs:"applicationKeys,omitempty"`
|
||||
}
|
||||
|
||||
@@ -33,6 +38,15 @@ type UserGroup struct {
|
||||
Name string `json:"name,omitempty" structs:"name,omitempty"`
|
||||
}
|
||||
|
||||
type userSearchParam struct {
|
||||
name string
|
||||
value string
|
||||
}
|
||||
|
||||
type userSearch []userSearchParam
|
||||
|
||||
type userSearchF func(userSearch) userSearch
|
||||
|
||||
// Get gets user info from JIRA
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/user-getUser
|
||||
@@ -81,6 +95,24 @@ func (s *UserService) Create(user *User) (*User, *Response, error) {
|
||||
return responseUser, resp, nil
|
||||
}
|
||||
|
||||
// Delete deletes an user from JIRA.
|
||||
// Returns http.StatusNoContent on success.
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-user-delete
|
||||
func (s *UserService) Delete(username string) (*Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("/rest/api/2/user?username=%s", username)
|
||||
req, err := s.client.NewRequest("DELETE", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := s.client.Do(req, nil)
|
||||
if err != nil {
|
||||
return resp, NewJiraError(resp, err)
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// GetGroups returns the groups which the user belongs to
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/user-getUserGroups
|
||||
@@ -99,12 +131,76 @@ func (s *UserService) GetGroups(username string) (*[]UserGroup, *Response, error
|
||||
return userGroups, resp, nil
|
||||
}
|
||||
|
||||
// Get information about the current logged-in user
|
||||
//
|
||||
// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-myself-get
|
||||
func (s *UserService) GetSelf() (*User, *Response, error) {
|
||||
const apiEndpoint = "rest/api/2/myself"
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
var user User
|
||||
resp, err := s.client.Do(req, &user)
|
||||
if err != nil {
|
||||
return nil, resp, NewJiraError(resp, err)
|
||||
}
|
||||
return &user, resp, nil
|
||||
}
|
||||
|
||||
// WithMaxResults sets the max results to return
|
||||
func WithMaxResults(maxResults int) userSearchF {
|
||||
return func(s userSearch) userSearch {
|
||||
s = append(s, userSearchParam{name: "maxResults", value: fmt.Sprintf("%d", maxResults)})
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
// WithStartAt set the start pager
|
||||
func WithStartAt(startAt int) userSearchF {
|
||||
return func(s userSearch) userSearch {
|
||||
s = append(s, userSearchParam{name: "startAt", value: fmt.Sprintf("%d", startAt)})
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
// WithActive sets the active users lookup
|
||||
func WithActive(active bool) userSearchF {
|
||||
return func(s userSearch) userSearch {
|
||||
s = append(s, userSearchParam{name: "includeActive", value: fmt.Sprintf("%t", active)})
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
// WithInactive sets the inactive users lookup
|
||||
func WithInactive(inactive bool) userSearchF {
|
||||
return func(s userSearch) userSearch {
|
||||
s = append(s, userSearchParam{name: "includeInactive", value: fmt.Sprintf("%t", inactive)})
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
// Find searches for user info from JIRA:
|
||||
// It can find users by email, username or name
|
||||
//
|
||||
// JIRA API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/user-findUsers
|
||||
func (s *UserService) Find(property string) ([]User, *Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("/rest/api/2/user/search?username=%s", property)
|
||||
func (s *UserService) Find(property string, tweaks ...userSearchF) ([]User, *Response, error) {
|
||||
search := []userSearchParam{
|
||||
{
|
||||
name: "username",
|
||||
value: property,
|
||||
},
|
||||
}
|
||||
for _, f := range tweaks {
|
||||
search = f(search)
|
||||
}
|
||||
|
||||
var queryString = ""
|
||||
for _, param := range search {
|
||||
queryString += param.name + "=" + param.value + "&"
|
||||
}
|
||||
|
||||
apiEndpoint := fmt.Sprintf("/rest/api/2/user/search?%s", queryString[:len(queryString)-1])
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
||||
3
vendor/github.com/andygrunwald/go-jira/version.go
generated
vendored
3
vendor/github.com/andygrunwald/go-jira/version.go
generated
vendored
@@ -18,12 +18,13 @@ type Version struct {
|
||||
Self string `json:"self,omitempty" structs:"self,omitempty"`
|
||||
ID string `json:"id,omitempty" structs:"id,omitempty"`
|
||||
Name string `json:"name,omitempty" structs:"name,omitempty"`
|
||||
Description string `json:"description,omitempty" structs:"name,omitempty"`
|
||||
Description string `json:"description,omitempty" structs:"description,omitempty"`
|
||||
Archived bool `json:"archived,omitempty" structs:"archived,omitempty"`
|
||||
Released bool `json:"released,omitempty" structs:"released,omitempty"`
|
||||
ReleaseDate string `json:"releaseDate,omitempty" structs:"releaseDate,omitempty"`
|
||||
UserReleaseDate string `json:"userReleaseDate,omitempty" structs:"userReleaseDate,omitempty"`
|
||||
ProjectID int `json:"projectId,omitempty" structs:"projectId,omitempty"` // Unlike other IDs, this is returned as a number
|
||||
StartDate string `json:"startDate,omitempty" structs:"startDate,omitempty"`
|
||||
}
|
||||
|
||||
// Get gets version info from JIRA
|
||||
|
||||
2
vendor/github.com/chzyer/readline/complete.go
generated
vendored
2
vendor/github.com/chzyer/readline/complete.go
generated
vendored
@@ -221,7 +221,7 @@ func (o *opCompleter) CompleteRefresh() {
|
||||
}
|
||||
buf.WriteString(string(same))
|
||||
buf.WriteString(string(c))
|
||||
buf.Write(bytes.Repeat([]byte(" "), colWidth-len(c)-len(same)))
|
||||
buf.Write(bytes.Repeat([]byte(" "), colWidth-runes.WidthAll(c)-runes.WidthAll(same)))
|
||||
|
||||
if inSelect {
|
||||
buf.WriteString("\033[0m")
|
||||
|
||||
3
vendor/github.com/containous/go-bindata/.gitignore
generated
vendored
Normal file
3
vendor/github.com/containous/go-bindata/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
.idea/
|
||||
vendor/
|
||||
dist/
|
||||
18
vendor/github.com/containous/go-bindata/.travis.yml
generated
vendored
Normal file
18
vendor/github.com/containous/go-bindata/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.x
|
||||
|
||||
install:
|
||||
- echo "TRAVIS_GO_VERSION=$TRAVIS_GO_VERSION"
|
||||
|
||||
deploy:
|
||||
- provider: releases
|
||||
api_key: ${GITHUB_TOKEN}
|
||||
file: dist/go-bindata
|
||||
skip_cleanup: true
|
||||
overwrite: true
|
||||
file_glob: true
|
||||
on:
|
||||
tags: true
|
||||
condition: $TRAVIS_GO_VERSION =~ ^1\.x$
|
||||
79
vendor/github.com/containous/go-bindata/CONTRIBUTING.md
generated
vendored
Normal file
79
vendor/github.com/containous/go-bindata/CONTRIBUTING.md
generated
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
## Contribution guidelines.
|
||||
|
||||
So you wish to contribute to this project? Fantastic!
|
||||
Here are a few guidelines to help you do this in a
|
||||
streamlined fashion.
|
||||
|
||||
|
||||
## Bug reports
|
||||
|
||||
When supplying a bug report, please consider the following guidelines.
|
||||
These serve to make it easier for us to address the issue and find a solution.
|
||||
Most of these are pretty self-evident, but sometimes it is still necessary
|
||||
to reiterate them.
|
||||
|
||||
* Be clear in the way you express the problem. Use simple language and
|
||||
just enough of it to clearly define the issue. Not everyone is a native
|
||||
English speaker. And while most can handle themselves pretty well,
|
||||
it helps to stay away from more esoteric vocabulary.
|
||||
|
||||
Be patient with non-native English speakers. If their bug reports
|
||||
or comments are hard to understand, just ask for clarification.
|
||||
Do not start guessing at their meaning, as this may just lead to
|
||||
more confusion and misunderstandings.
|
||||
* Clearly define any information which is relevant to the problem.
|
||||
This includes library versions, operating system and any other
|
||||
external dependencies which may be needed.
|
||||
* Where applicable, provide a step-by-step listing of the way to
|
||||
reproduce the problem. Make sure this is the simplest possible
|
||||
way to do so. Omit any and all unneccesary steps, because they may
|
||||
just complicate our understanding of the real problem.
|
||||
If need be, create a whole new code project on your local machine,
|
||||
which specifically tries to create the problem you are running into;
|
||||
nothing more, nothing less.
|
||||
|
||||
Include this program in the bug report. It often suffices to paste
|
||||
the code in a [Gist](https://gist.github.com) or on the
|
||||
[Go playground](http://play.golang.org).
|
||||
* If possible, provide us with a listing of the steps you have already
|
||||
undertaken to solve the problem. This can save us a great deal of
|
||||
wasted time, trying out solutions you have already covered.
|
||||
|
||||
|
||||
## Pull requests
|
||||
|
||||
Bug reports are great. Supplying fixes to bugs is even better.
|
||||
When submitting a pull request, the following guidelines are
|
||||
good to keep in mind:
|
||||
|
||||
* `go fmt`: **Always** run your code through `go fmt`, before
|
||||
committing it. Code has to be readable by many different
|
||||
people. And the only way this will be as painless as possible,
|
||||
is if we all stick to the same code style.
|
||||
|
||||
Some of our projects may have automated build-servers hooked up
|
||||
to commit hooks. These will vet any submitted code and determine
|
||||
if it meets a set of properties. One of which is code formatting.
|
||||
These servers will outright deny a submission which has not been
|
||||
run through `go fmt`, even if the code itself is correct.
|
||||
|
||||
We try to maintain a zero-tolerance policy on this matter,
|
||||
because consistently formatted code makes life a great deal
|
||||
easier for everyone involved.
|
||||
* Commit log messages: When committing changes, do so often and
|
||||
clearly -- Even if you have changed only 1 character in a code
|
||||
comment. This means that commit log messages should clearly state
|
||||
exactly what the change does and why. If it fixes a known issue,
|
||||
then mention the issue number in the commit log. E.g.:
|
||||
|
||||
> Fixes return value for `foo/boo.Baz()` to be consistent with
|
||||
> the rest of the API. This addresses issue #32
|
||||
|
||||
Do not pile a lot of unrelated changes into a single commit.
|
||||
Pick and choose only those changes for a single commit, which are
|
||||
directly related. We would much rather see a hundred commits
|
||||
saying nothing but `"Runs go fmt"` in between any real fixes
|
||||
than have these style changes embedded in those real fixes.
|
||||
It creates a lot of noise when trying to review code.
|
||||
|
||||
|
||||
3
vendor/github.com/containous/go-bindata/LICENSE
generated
vendored
Normal file
3
vendor/github.com/containous/go-bindata/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
|
||||
license. Its contents can be found at:
|
||||
http://creativecommons.org/publicdomain/zero/1.0
|
||||
31
vendor/github.com/containous/go-bindata/Makefile
generated
vendored
Normal file
31
vendor/github.com/containous/go-bindata/Makefile
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
.PHONY: all clean checks test build image dependencies
|
||||
|
||||
SRCS = $(shell git ls-files '*.go' | grep -v '^vendor/')
|
||||
|
||||
MAIN_DIRECTORY := ./go-bindata/
|
||||
BIN_OUTPUT := dist/go-bindata
|
||||
|
||||
TAG_NAME := $(shell git tag -l --contains HEAD)
|
||||
SHA := $(shell git rev-parse HEAD)
|
||||
VERSION := $(if $(TAG_NAME),$(TAG_NAME),$(SHA))
|
||||
|
||||
default: clean test build
|
||||
|
||||
clean:
|
||||
rm -rf dist/ builds/ cover.out
|
||||
|
||||
build: clean
|
||||
@echo Version: $(VERSION)
|
||||
go build -v -ldflags '-X "main.AppVersion=${VERSION}"' -o ${BIN_OUTPUT} ${MAIN_DIRECTORY}
|
||||
|
||||
dependencies:
|
||||
dep ensure -v
|
||||
|
||||
test: clean
|
||||
go test -v -cover ./...
|
||||
|
||||
testdata:
|
||||
make -C testdata
|
||||
|
||||
fmt:
|
||||
gofmt -s -l -w $(SRCS)
|
||||
197
vendor/github.com/containous/go-bindata/README.md
generated
vendored
Normal file
197
vendor/github.com/containous/go-bindata/README.md
generated
vendored
Normal file
@@ -0,0 +1,197 @@
|
||||
## IMPORTANT
|
||||
|
||||
**This a copy of https://github.com/jteeuwen/go-bindata/ due to the disappearance of https://github.com/jteeuwen on GitHub.**
|
||||
|
||||
The original code is in the branch [jteeuwen](https://github.com/containous/go-bindata/tree/jteeuwen).
|
||||
|
||||
In the branch `master`, we have only change some imports to be working with `go get`.
|
||||
|
||||
## bindata
|
||||
|
||||
This package converts any file into managable Go source code. Useful for
|
||||
embedding binary data into a go program. The file data is optionally gzip
|
||||
compressed before being converted to a raw byte slice.
|
||||
|
||||
It comes with a command line tool in the `go-bindata` sub directory.
|
||||
This tool offers a set of command line options, used to customize the
|
||||
output being generated.
|
||||
|
||||
|
||||
### Installation
|
||||
|
||||
To install the library and command line program, use the following:
|
||||
|
||||
go get -u github.com/containous/go-bindata/...
|
||||
|
||||
|
||||
### Usage
|
||||
|
||||
Conversion is done on one or more sets of files. They are all embedded in a new
|
||||
Go source file, along with a table of contents and an `Asset` function,
|
||||
which allows quick access to the asset, based on its name.
|
||||
|
||||
The simplest invocation generates a `bindata.go` file in the current
|
||||
working directory. It includes all assets from the `data` directory.
|
||||
|
||||
$ go-bindata data/
|
||||
|
||||
To include all input sub-directories recursively, use the elipsis postfix
|
||||
as defined for Go import paths. Otherwise it will only consider assets in the
|
||||
input directory itself.
|
||||
|
||||
$ go-bindata data/...
|
||||
|
||||
To specify the name of the output file being generated, we use the following:
|
||||
|
||||
$ go-bindata -o myfile.go data/
|
||||
|
||||
Multiple input directories can be specified if necessary.
|
||||
|
||||
$ go-bindata dir1/... /path/to/dir2/... dir3
|
||||
|
||||
|
||||
The following paragraphs detail some of the command line options which can be
|
||||
supplied to `go-bindata`. Refer to the `testdata/out` directory for various
|
||||
output examples from the assets in `testdata/in`. Each example uses different
|
||||
command line options.
|
||||
|
||||
To ignore files, pass in regexes using -ignore, for example:
|
||||
|
||||
$ go-bindata -ignore=\\.gitignore data/...
|
||||
|
||||
### Accessing an asset
|
||||
|
||||
To access asset data, we use the `Asset(string) ([]byte, error)` function which
|
||||
is included in the generated output.
|
||||
|
||||
data, err := Asset("pub/style/foo.css")
|
||||
if err != nil {
|
||||
// Asset was not found.
|
||||
}
|
||||
|
||||
// use asset data
|
||||
|
||||
|
||||
### Debug vs Release builds
|
||||
|
||||
When invoking the program with the `-debug` flag, the generated code does
|
||||
not actually include the asset data. Instead, it generates function stubs
|
||||
which load the data from the original file on disk. The asset API remains
|
||||
identical between debug and release builds, so your code will not have to
|
||||
change.
|
||||
|
||||
This is useful during development when you expect the assets to change often.
|
||||
The host application using these assets uses the same API in both cases and
|
||||
will not have to care where the actual data comes from.
|
||||
|
||||
An example is a Go webserver with some embedded, static web content like
|
||||
HTML, JS and CSS files. While developing it, you do not want to rebuild the
|
||||
whole server and restart it every time you make a change to a bit of
|
||||
javascript. You just want to build and launch the server once. Then just press
|
||||
refresh in the browser to see those changes. Embedding the assets with the
|
||||
`debug` flag allows you to do just that. When you are finished developing and
|
||||
ready for deployment, just re-invoke `go-bindata` without the `-debug` flag.
|
||||
It will now embed the latest version of the assets.
|
||||
|
||||
|
||||
### Lower memory footprint
|
||||
|
||||
Using the `-nomemcopy` flag, will alter the way the output file is generated.
|
||||
It will employ a hack that allows us to read the file data directly from
|
||||
the compiled program's `.rodata` section. This ensures that when we call
|
||||
call our generated function, we omit unnecessary memcopies.
|
||||
|
||||
The downside of this, is that it requires dependencies on the `reflect` and
|
||||
`unsafe` packages. These may be restricted on platforms like AppEngine and
|
||||
thus prevent you from using this mode.
|
||||
|
||||
Another disadvantage is that the byte slice we create, is strictly read-only.
|
||||
For most use-cases this is not a problem, but if you ever try to alter the
|
||||
returned byte slice, a runtime panic is thrown. Use this mode only on target
|
||||
platforms where memory constraints are an issue.
|
||||
|
||||
The default behaviour is to use the old code generation method. This
|
||||
prevents the two previously mentioned issues, but will employ at least one
|
||||
extra memcopy and thus increase memory requirements.
|
||||
|
||||
For instance, consider the following two examples:
|
||||
|
||||
This would be the default mode, using an extra memcopy but gives a safe
|
||||
implementation without dependencies on `reflect` and `unsafe`:
|
||||
|
||||
```go
|
||||
func myfile() []byte {
|
||||
return []byte{0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a}
|
||||
}
|
||||
```
|
||||
|
||||
Here is the same functionality, but uses the `.rodata` hack.
|
||||
The byte slice returned from this example can not be written to without
|
||||
generating a runtime error.
|
||||
|
||||
```go
|
||||
var _myfile = "\x89\x50\x4e\x47\x0d\x0a\x1a"
|
||||
|
||||
func myfile() []byte {
|
||||
var empty [0]byte
|
||||
sx := (*reflect.StringHeader)(unsafe.Pointer(&_myfile))
|
||||
b := empty[:]
|
||||
bx := (*reflect.SliceHeader)(unsafe.Pointer(&b))
|
||||
bx.Data = sx.Data
|
||||
bx.Len = len(_myfile)
|
||||
bx.Cap = bx.Len
|
||||
return b
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Optional compression
|
||||
|
||||
When the `-nocompress` flag is given, the supplied resource is *not* GZIP
|
||||
compressed before being turned into Go code. The data should still be accessed
|
||||
through a function call, so nothing changes in the usage of the generated file.
|
||||
|
||||
This feature is useful if you do not care for compression, or the supplied
|
||||
resource is already compressed. Doing it again would not add any value and may
|
||||
even increase the size of the data.
|
||||
|
||||
The default behaviour of the program is to use compression.
|
||||
|
||||
|
||||
### Path prefix stripping
|
||||
|
||||
The keys used in the `_bindata` map, are the same as the input file name
|
||||
passed to `go-bindata`. This includes the path. In most cases, this is not
|
||||
desireable, as it puts potentially sensitive information in your code base.
|
||||
For this purpose, the tool supplies another command line flag `-prefix`.
|
||||
This accepts a portion of a path name, which should be stripped off from
|
||||
the map keys and function names.
|
||||
|
||||
For example, running without the `-prefix` flag, we get:
|
||||
|
||||
$ go-bindata /path/to/templates/
|
||||
|
||||
_bindata["/path/to/templates/foo.html"] = path_to_templates_foo_html
|
||||
|
||||
Running with the `-prefix` flag, we get:
|
||||
|
||||
$ go-bindata -prefix "/path/to/" /path/to/templates/
|
||||
|
||||
_bindata["templates/foo.html"] = templates_foo_html
|
||||
|
||||
|
||||
### Build tags
|
||||
|
||||
With the optional `-tags` flag, you can specify any go build tags that
|
||||
must be fulfilled for the output file to be included in a build. This
|
||||
is useful when including binary data in multiple formats, where the desired
|
||||
format is specified at build time with the appropriate tags.
|
||||
|
||||
The tags are appended to a `// +build` line in the beginning of the output file
|
||||
and must follow the build tags syntax specified by the go tool.
|
||||
|
||||
### Related projects
|
||||
|
||||
[go-bindata-assetfs](https://github.com/elazarl/go-bindata-assetfs#readme) -
|
||||
implements `http.FileSystem` interface. Allows you to serve assets with `net/http`.
|
||||
|
||||
12
vendor/github.com/containous/go-bindata/asset.go
generated
vendored
Normal file
12
vendor/github.com/containous/go-bindata/asset.go
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
|
||||
// license. Its contents can be found at:
|
||||
// http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
package bindata
|
||||
|
||||
// Asset holds information about a single asset to be processed.
|
||||
type Asset struct {
|
||||
Path string // Full file path.
|
||||
Name string // Key used in TOC -- name by which asset is referenced.
|
||||
Func string // Function name for the procedure returning the asset contents.
|
||||
}
|
||||
44
vendor/github.com/containous/go-bindata/bytewriter.go
generated
vendored
Normal file
44
vendor/github.com/containous/go-bindata/bytewriter.go
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
|
||||
// license. Its contents can be found at:
|
||||
// http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
package bindata
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
var (
|
||||
newline = []byte{'\n'}
|
||||
dataindent = []byte{'\t', '\t'}
|
||||
space = []byte{' '}
|
||||
)
|
||||
|
||||
type ByteWriter struct {
|
||||
io.Writer
|
||||
c int
|
||||
}
|
||||
|
||||
func (w *ByteWriter) Write(p []byte) (n int, err error) {
|
||||
if len(p) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
for n = range p {
|
||||
if w.c%12 == 0 {
|
||||
w.Writer.Write(newline)
|
||||
w.Writer.Write(dataindent)
|
||||
w.c = 0
|
||||
} else {
|
||||
w.Writer.Write(space)
|
||||
}
|
||||
|
||||
fmt.Fprintf(w.Writer, "0x%02x,", p[n])
|
||||
w.c++
|
||||
}
|
||||
|
||||
n++
|
||||
|
||||
return
|
||||
}
|
||||
203
vendor/github.com/containous/go-bindata/config.go
generated
vendored
Normal file
203
vendor/github.com/containous/go-bindata/config.go
generated
vendored
Normal file
@@ -0,0 +1,203 @@
|
||||
// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
|
||||
// license. Its contents can be found at:
|
||||
// http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
package bindata
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
// InputConfig defines options on a asset directory to be convert.
|
||||
type InputConfig struct {
|
||||
// Path defines a directory containing asset files to be included
|
||||
// in the generated output.
|
||||
Path string
|
||||
|
||||
// Recursive defines whether subdirectories of Path
|
||||
// should be recursively included in the conversion.
|
||||
Recursive bool
|
||||
}
|
||||
|
||||
// Config defines a set of options for the asset conversion.
|
||||
type Config struct {
|
||||
// Name of the package to use. Defaults to 'main'.
|
||||
Package string
|
||||
|
||||
// Tags specify a set of optional build tags, which should be
|
||||
// included in the generated output. The tags are appended to a
|
||||
// `// +build` line in the beginning of the output file
|
||||
// and must follow the build tags syntax specified by the go tool.
|
||||
Tags string
|
||||
|
||||
// Input defines the directory path, containing all asset files as
|
||||
// well as whether to recursively process assets in any sub directories.
|
||||
Input []InputConfig
|
||||
|
||||
// Output defines the output file for the generated code.
|
||||
// If left empty, this defaults to 'bindata.go' in the current
|
||||
// working directory.
|
||||
Output string
|
||||
|
||||
// Prefix defines a path prefix which should be stripped from all
|
||||
// file names when generating the keys in the table of contents.
|
||||
// For example, running without the `-prefix` flag, we get:
|
||||
//
|
||||
// $ go-bindata /path/to/templates
|
||||
// go_bindata["/path/to/templates/foo.html"] = _path_to_templates_foo_html
|
||||
//
|
||||
// Running with the `-prefix` flag, we get:
|
||||
//
|
||||
// $ go-bindata -prefix "/path/to/" /path/to/templates/foo.html
|
||||
// go_bindata["templates/foo.html"] = templates_foo_html
|
||||
Prefix string
|
||||
|
||||
// NoMemCopy will alter the way the output file is generated.
|
||||
//
|
||||
// It will employ a hack that allows us to read the file data directly from
|
||||
// the compiled program's `.rodata` section. This ensures that when we call
|
||||
// call our generated function, we omit unnecessary mem copies.
|
||||
//
|
||||
// The downside of this, is that it requires dependencies on the `reflect` and
|
||||
// `unsafe` packages. These may be restricted on platforms like AppEngine and
|
||||
// thus prevent you from using this mode.
|
||||
//
|
||||
// Another disadvantage is that the byte slice we create, is strictly read-only.
|
||||
// For most use-cases this is not a problem, but if you ever try to alter the
|
||||
// returned byte slice, a runtime panic is thrown. Use this mode only on target
|
||||
// platforms where memory constraints are an issue.
|
||||
//
|
||||
// The default behaviour is to use the old code generation method. This
|
||||
// prevents the two previously mentioned issues, but will employ at least one
|
||||
// extra memcopy and thus increase memory requirements.
|
||||
//
|
||||
// For instance, consider the following two examples:
|
||||
//
|
||||
// This would be the default mode, using an extra memcopy but gives a safe
|
||||
// implementation without dependencies on `reflect` and `unsafe`:
|
||||
//
|
||||
// func myfile() []byte {
|
||||
// return []byte{0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a}
|
||||
// }
|
||||
//
|
||||
// Here is the same functionality, but uses the `.rodata` hack.
|
||||
// The byte slice returned from this example can not be written to without
|
||||
// generating a runtime error.
|
||||
//
|
||||
// var _myfile = "\x89\x50\x4e\x47\x0d\x0a\x1a"
|
||||
//
|
||||
// func myfile() []byte {
|
||||
// var empty [0]byte
|
||||
// sx := (*reflect.StringHeader)(unsafe.Pointer(&_myfile))
|
||||
// b := empty[:]
|
||||
// bx := (*reflect.SliceHeader)(unsafe.Pointer(&b))
|
||||
// bx.Data = sx.Data
|
||||
// bx.Len = len(_myfile)
|
||||
// bx.Cap = bx.Len
|
||||
// return b
|
||||
// }
|
||||
NoMemCopy bool
|
||||
|
||||
// NoCompress means the assets are /not/ GZIP compressed before being turned
|
||||
// into Go code. The generated function will automatically unzip
|
||||
// the file data when called. Defaults to false.
|
||||
NoCompress bool
|
||||
|
||||
// Perform a debug build. This generates an asset file, which
|
||||
// loads the asset contents directly from disk at their original
|
||||
// location, instead of embedding the contents in the code.
|
||||
//
|
||||
// This is mostly useful if you anticipate that the assets are
|
||||
// going to change during your development cycle. You will always
|
||||
// want your code to access the latest version of the asset.
|
||||
// Only in release mode, will the assets actually be embedded
|
||||
// in the code. The default behaviour is Release mode.
|
||||
Debug bool
|
||||
|
||||
// Perform a dev build, which is nearly identical to the debug option. The
|
||||
// only difference is that instead of absolute file paths in generated code,
|
||||
// it expects a variable, `rootDir`, to be set in the generated code's
|
||||
// package (the author needs to do this manually), which it then prepends to
|
||||
// an asset's name to construct the file path on disk.
|
||||
//
|
||||
// This is mainly so you can push the generated code file to a shared
|
||||
// repository.
|
||||
Dev bool
|
||||
|
||||
// When true, size, mode and modtime are not preserved from files
|
||||
NoMetadata bool
|
||||
// When nonzero, use this as mode for all files.
|
||||
Mode uint
|
||||
// When nonzero, use this as unix timestamp for all files.
|
||||
ModTime int64
|
||||
|
||||
// Ignores any filenames matching the regex pattern specified, e.g.
|
||||
// path/to/file.ext will ignore only that file, or \\.gitignore
|
||||
// will match any .gitignore file.
|
||||
//
|
||||
// This parameter can be provided multiple times.
|
||||
Ignore []*regexp.Regexp
|
||||
}
|
||||
|
||||
// NewConfig returns a default configuration struct.
|
||||
func NewConfig() *Config {
|
||||
c := new(Config)
|
||||
c.Package = "main"
|
||||
c.NoMemCopy = false
|
||||
c.NoCompress = false
|
||||
c.Debug = false
|
||||
c.Output = "./bindata.go"
|
||||
c.Ignore = make([]*regexp.Regexp, 0)
|
||||
return c
|
||||
}
|
||||
|
||||
// validate ensures the config has sane values.
|
||||
// Part of which means checking if certain file/directory paths exist.
|
||||
func (c *Config) validate() error {
|
||||
if len(c.Package) == 0 {
|
||||
return fmt.Errorf("Missing package name")
|
||||
}
|
||||
|
||||
for _, input := range c.Input {
|
||||
_, err := os.Lstat(input.Path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to stat input path '%s': %v", input.Path, err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(c.Output) == 0 {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to determine current working directory.")
|
||||
}
|
||||
|
||||
c.Output = filepath.Join(cwd, "bindata.go")
|
||||
}
|
||||
|
||||
stat, err := os.Lstat(c.Output)
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
return fmt.Errorf("Output path: %v", err)
|
||||
}
|
||||
|
||||
// File does not exist. This is fine, just make
|
||||
// sure the directory it is to be in exists.
|
||||
dir, _ := filepath.Split(c.Output)
|
||||
if dir != "" {
|
||||
err = os.MkdirAll(dir, 0744)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("Create output directory: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if stat != nil && stat.IsDir() {
|
||||
return fmt.Errorf("Output path is a directory.")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
261
vendor/github.com/containous/go-bindata/convert.go
generated
vendored
Normal file
261
vendor/github.com/containous/go-bindata/convert.go
generated
vendored
Normal file
@@ -0,0 +1,261 @@
|
||||
// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
|
||||
// license. Its contents can be found at:
|
||||
// http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
package bindata
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
// Translate reads assets from an input directory, converts them
|
||||
// to Go code and writes new files to the output specified
|
||||
// in the given configuration.
|
||||
func Translate(c *Config) error {
|
||||
var toc []Asset
|
||||
|
||||
// Ensure our configuration has sane values.
|
||||
err := c.validate()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var knownFuncs = make(map[string]int)
|
||||
var visitedPaths = make(map[string]bool)
|
||||
// Locate all the assets.
|
||||
for _, input := range c.Input {
|
||||
err = findFiles(input.Path, c.Prefix, input.Recursive, &toc, c.Ignore, knownFuncs, visitedPaths)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Create output file.
|
||||
fd, err := os.Create(c.Output)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer fd.Close()
|
||||
|
||||
// Create a buffered writer for better performance.
|
||||
bfd := bufio.NewWriter(fd)
|
||||
defer bfd.Flush()
|
||||
|
||||
// Write the header. This makes e.g. Github ignore diffs in generated files.
|
||||
if _, err = fmt.Fprint(bfd, "// Code generated by go-bindata.\n"); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = fmt.Fprint(bfd, "// sources:\n"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, asset := range toc {
|
||||
relative, _ := filepath.Rel(wd, asset.Path)
|
||||
if _, err = fmt.Fprintf(bfd, "// %s\n", filepath.ToSlash(relative)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if _, err = fmt.Fprint(bfd, "// DO NOT EDIT!\n\n"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Write build tags, if applicable.
|
||||
if len(c.Tags) > 0 {
|
||||
if _, err = fmt.Fprintf(bfd, "// +build %s\n\n", c.Tags); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Write package declaration.
|
||||
_, err = fmt.Fprintf(bfd, "package %s\n\n", c.Package)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Write assets.
|
||||
if c.Debug || c.Dev {
|
||||
err = writeDebug(bfd, c, toc)
|
||||
} else {
|
||||
err = writeRelease(bfd, c, toc)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Write table of contents
|
||||
if err := writeTOC(bfd, toc); err != nil {
|
||||
return err
|
||||
}
|
||||
// Write hierarchical tree of assets
|
||||
if err := writeTOCTree(bfd, toc); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Write restore procedure
|
||||
return writeRestore(bfd)
|
||||
}
|
||||
|
||||
// Implement sort.Interface for []os.FileInfo based on Name()
|
||||
type ByName []os.FileInfo
|
||||
|
||||
func (v ByName) Len() int { return len(v) }
|
||||
func (v ByName) Swap(i, j int) { v[i], v[j] = v[j], v[i] }
|
||||
func (v ByName) Less(i, j int) bool { return v[i].Name() < v[j].Name() }
|
||||
|
||||
// findFiles recursively finds all the file paths in the given directory tree.
|
||||
// They are added to the given map as keys. Values will be safe function names
|
||||
// for each file, which will be used when generating the output code.
|
||||
func findFiles(dir, prefix string, recursive bool, toc *[]Asset, ignore []*regexp.Regexp, knownFuncs map[string]int, visitedPaths map[string]bool) error {
|
||||
dirpath := dir
|
||||
if len(prefix) > 0 {
|
||||
dirpath, _ = filepath.Abs(dirpath)
|
||||
prefix, _ = filepath.Abs(prefix)
|
||||
prefix = filepath.ToSlash(prefix)
|
||||
}
|
||||
|
||||
fi, err := os.Stat(dirpath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var list []os.FileInfo
|
||||
|
||||
if !fi.IsDir() {
|
||||
dirpath = filepath.Dir(dirpath)
|
||||
list = []os.FileInfo{fi}
|
||||
} else {
|
||||
visitedPaths[dirpath] = true
|
||||
fd, err := os.Open(dirpath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer fd.Close()
|
||||
|
||||
list, err = fd.Readdir(0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Sort to make output stable between invocations
|
||||
sort.Sort(ByName(list))
|
||||
}
|
||||
|
||||
for _, file := range list {
|
||||
var asset Asset
|
||||
asset.Path = filepath.Join(dirpath, file.Name())
|
||||
asset.Name = filepath.ToSlash(asset.Path)
|
||||
|
||||
ignoring := false
|
||||
for _, re := range ignore {
|
||||
if re.MatchString(asset.Path) {
|
||||
ignoring = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if ignoring {
|
||||
continue
|
||||
}
|
||||
|
||||
if file.IsDir() {
|
||||
if recursive {
|
||||
recursivePath := filepath.Join(dir, file.Name())
|
||||
visitedPaths[asset.Path] = true
|
||||
findFiles(recursivePath, prefix, recursive, toc, ignore, knownFuncs, visitedPaths)
|
||||
}
|
||||
continue
|
||||
} else if file.Mode()&os.ModeSymlink == os.ModeSymlink {
|
||||
var linkPath string
|
||||
if linkPath, err = os.Readlink(asset.Path); err != nil {
|
||||
return err
|
||||
}
|
||||
if !filepath.IsAbs(linkPath) {
|
||||
if linkPath, err = filepath.Abs(dirpath + "/" + linkPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if _, ok := visitedPaths[linkPath]; !ok {
|
||||
visitedPaths[linkPath] = true
|
||||
findFiles(asset.Path, prefix, recursive, toc, ignore, knownFuncs, visitedPaths)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.HasPrefix(asset.Name, prefix) {
|
||||
asset.Name = asset.Name[len(prefix):]
|
||||
} else {
|
||||
asset.Name = filepath.Join(dir, file.Name())
|
||||
}
|
||||
|
||||
// If we have a leading slash, get rid of it.
|
||||
if len(asset.Name) > 0 && asset.Name[0] == '/' {
|
||||
asset.Name = asset.Name[1:]
|
||||
}
|
||||
|
||||
// This shouldn't happen.
|
||||
if len(asset.Name) == 0 {
|
||||
return fmt.Errorf("Invalid file: %v", asset.Path)
|
||||
}
|
||||
|
||||
asset.Func = safeFunctionName(asset.Name, knownFuncs)
|
||||
asset.Path, _ = filepath.Abs(asset.Path)
|
||||
*toc = append(*toc, asset)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var regFuncName = regexp.MustCompile(`[^a-zA-Z0-9_]`)
|
||||
|
||||
// safeFunctionName converts the given name into a name
|
||||
// which qualifies as a valid function identifier. It
|
||||
// also compares against a known list of functions to
|
||||
// prevent conflict based on name translation.
|
||||
func safeFunctionName(name string, knownFuncs map[string]int) string {
|
||||
var inBytes, outBytes []byte
|
||||
var toUpper bool
|
||||
|
||||
name = strings.ToLower(name)
|
||||
inBytes = []byte(name)
|
||||
|
||||
for i := 0; i < len(inBytes); i++ {
|
||||
if regFuncName.Match([]byte{inBytes[i]}) {
|
||||
toUpper = true
|
||||
} else if toUpper {
|
||||
outBytes = append(outBytes, []byte(strings.ToUpper(string(inBytes[i])))...)
|
||||
toUpper = false
|
||||
} else {
|
||||
outBytes = append(outBytes, inBytes[i])
|
||||
}
|
||||
}
|
||||
|
||||
name = string(outBytes)
|
||||
|
||||
// Identifier can't start with a digit.
|
||||
if unicode.IsDigit(rune(name[0])) {
|
||||
name = "_" + name
|
||||
}
|
||||
|
||||
if num, ok := knownFuncs[name]; ok {
|
||||
knownFuncs[name] = num + 1
|
||||
name = fmt.Sprintf("%s%d", name, num)
|
||||
} else {
|
||||
knownFuncs[name] = 2
|
||||
}
|
||||
|
||||
return name
|
||||
}
|
||||
87
vendor/github.com/containous/go-bindata/debug.go
generated
vendored
Normal file
87
vendor/github.com/containous/go-bindata/debug.go
generated
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
|
||||
// license. Its contents can be found at:
|
||||
// http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
package bindata
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// writeDebug writes the debug code file.
|
||||
func writeDebug(w io.Writer, c *Config, toc []Asset) error {
|
||||
err := writeDebugHeader(w)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i := range toc {
|
||||
err = writeDebugAsset(w, c, &toc[i])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// writeDebugHeader writes output file headers.
|
||||
// This targets debug builds.
|
||||
func writeDebugHeader(w io.Writer) error {
|
||||
_, err := fmt.Fprintf(w, `import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// bindataRead reads the given file from disk. It returns an error on failure.
|
||||
func bindataRead(path, name string) ([]byte, error) {
|
||||
buf, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Error reading asset %%s at %%s: %%v", name, path, err)
|
||||
}
|
||||
return buf, err
|
||||
}
|
||||
|
||||
type asset struct {
|
||||
bytes []byte
|
||||
info os.FileInfo
|
||||
}
|
||||
|
||||
`)
|
||||
return err
|
||||
}
|
||||
|
||||
// writeDebugAsset write a debug entry for the given asset.
|
||||
// A debug entry is simply a function which reads the asset from
|
||||
// the original file (e.g.: from disk).
|
||||
func writeDebugAsset(w io.Writer, c *Config, asset *Asset) error {
|
||||
pathExpr := fmt.Sprintf("%q", asset.Path)
|
||||
if c.Dev {
|
||||
pathExpr = fmt.Sprintf("filepath.Join(rootDir, %q)", asset.Name)
|
||||
}
|
||||
|
||||
_, err := fmt.Fprintf(w, `// %s reads file data from disk. It returns an error on failure.
|
||||
func %s() (*asset, error) {
|
||||
path := %s
|
||||
name := %q
|
||||
bytes, err := bindataRead(path, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fi, err := os.Stat(path)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Error reading asset info %%s at %%s: %%v", name, path, err)
|
||||
}
|
||||
|
||||
a := &asset{bytes: bytes, info: fi}
|
||||
return a, err
|
||||
}
|
||||
|
||||
`, asset.Func, asset.Func, pathExpr, asset.Name)
|
||||
return err
|
||||
}
|
||||
129
vendor/github.com/containous/go-bindata/doc.go
generated
vendored
Normal file
129
vendor/github.com/containous/go-bindata/doc.go
generated
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
|
||||
// license. Its contents can be found at:
|
||||
// http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
/*
|
||||
bindata converts any file into managable Go source code. Useful for
|
||||
embedding binary data into a go program. The file data is optionally gzip
|
||||
compressed before being converted to a raw byte slice.
|
||||
|
||||
The following paragraphs cover some of the customization options
|
||||
which can be specified in the Config struct, which must be passed into
|
||||
the Translate() call.
|
||||
|
||||
|
||||
Debug vs Release builds
|
||||
|
||||
When used with the `Debug` option, the generated code does not actually include
|
||||
the asset data. Instead, it generates function stubs which load the data from
|
||||
the original file on disk. The asset API remains identical between debug and
|
||||
release builds, so your code will not have to change.
|
||||
|
||||
This is useful during development when you expect the assets to change often.
|
||||
The host application using these assets uses the same API in both cases and
|
||||
will not have to care where the actual data comes from.
|
||||
|
||||
An example is a Go webserver with some embedded, static web content like
|
||||
HTML, JS and CSS files. While developing it, you do not want to rebuild the
|
||||
whole server and restart it every time you make a change to a bit of
|
||||
javascript. You just want to build and launch the server once. Then just press
|
||||
refresh in the browser to see those changes. Embedding the assets with the
|
||||
`debug` flag allows you to do just that. When you are finished developing and
|
||||
ready for deployment, just re-invoke `go-bindata` without the `-debug` flag.
|
||||
It will now embed the latest version of the assets.
|
||||
|
||||
|
||||
Lower memory footprint
|
||||
|
||||
The `NoMemCopy` option will alter the way the output file is generated.
|
||||
It will employ a hack that allows us to read the file data directly from
|
||||
the compiled program's `.rodata` section. This ensures that when we call
|
||||
call our generated function, we omit unnecessary memcopies.
|
||||
|
||||
The downside of this, is that it requires dependencies on the `reflect` and
|
||||
`unsafe` packages. These may be restricted on platforms like AppEngine and
|
||||
thus prevent you from using this mode.
|
||||
|
||||
Another disadvantage is that the byte slice we create, is strictly read-only.
|
||||
For most use-cases this is not a problem, but if you ever try to alter the
|
||||
returned byte slice, a runtime panic is thrown. Use this mode only on target
|
||||
platforms where memory constraints are an issue.
|
||||
|
||||
The default behaviour is to use the old code generation method. This
|
||||
prevents the two previously mentioned issues, but will employ at least one
|
||||
extra memcopy and thus increase memory requirements.
|
||||
|
||||
For instance, consider the following two examples:
|
||||
|
||||
This would be the default mode, using an extra memcopy but gives a safe
|
||||
implementation without dependencies on `reflect` and `unsafe`:
|
||||
|
||||
func myfile() []byte {
|
||||
return []byte{0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a}
|
||||
}
|
||||
|
||||
Here is the same functionality, but uses the `.rodata` hack.
|
||||
The byte slice returned from this example can not be written to without
|
||||
generating a runtime error.
|
||||
|
||||
var _myfile = "\x89\x50\x4e\x47\x0d\x0a\x1a"
|
||||
|
||||
func myfile() []byte {
|
||||
var empty [0]byte
|
||||
sx := (*reflect.StringHeader)(unsafe.Pointer(&_myfile))
|
||||
b := empty[:]
|
||||
bx := (*reflect.SliceHeader)(unsafe.Pointer(&b))
|
||||
bx.Data = sx.Data
|
||||
bx.Len = len(_myfile)
|
||||
bx.Cap = bx.Len
|
||||
return b
|
||||
}
|
||||
|
||||
|
||||
Optional compression
|
||||
|
||||
The NoCompress option indicates that the supplied assets are *not* GZIP
|
||||
compressed before being turned into Go code. The data should still be accessed
|
||||
through a function call, so nothing changes in the API.
|
||||
|
||||
This feature is useful if you do not care for compression, or the supplied
|
||||
resource is already compressed. Doing it again would not add any value and may
|
||||
even increase the size of the data.
|
||||
|
||||
The default behaviour of the program is to use compression.
|
||||
|
||||
|
||||
Path prefix stripping
|
||||
|
||||
The keys used in the `_bindata` map are the same as the input file name
|
||||
passed to `go-bindata`. This includes the path. In most cases, this is not
|
||||
desireable, as it puts potentially sensitive information in your code base.
|
||||
For this purpose, the tool supplies another command line flag `-prefix`.
|
||||
This accepts a portion of a path name, which should be stripped off from
|
||||
the map keys and function names.
|
||||
|
||||
For example, running without the `-prefix` flag, we get:
|
||||
|
||||
$ go-bindata /path/to/templates/
|
||||
|
||||
_bindata["/path/to/templates/foo.html"] = path_to_templates_foo_html
|
||||
|
||||
Running with the `-prefix` flag, we get:
|
||||
|
||||
$ go-bindata -prefix "/path/to/" /path/to/templates/
|
||||
|
||||
_bindata["templates/foo.html"] = templates_foo_html
|
||||
|
||||
|
||||
Build tags
|
||||
|
||||
With the optional Tags field, you can specify any go build tags that
|
||||
must be fulfilled for the output file to be included in a build. This
|
||||
is useful when including binary data in multiple formats, where the desired
|
||||
format is specified at build time with the appropriate tags.
|
||||
|
||||
The tags are appended to a `// +build` line in the beginning of the output file
|
||||
and must follow the build tags syntax specified by the go tool.
|
||||
|
||||
*/
|
||||
package bindata
|
||||
22
vendor/github.com/containous/go-bindata/go-bindata/AppendSliceValue.go
generated
vendored
Normal file
22
vendor/github.com/containous/go-bindata/go-bindata/AppendSliceValue.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
package main
|
||||
|
||||
import "strings"
|
||||
|
||||
// borrowed from https://github.com/hashicorp/serf/blob/master/command/agent/flag_slice_value.go
|
||||
|
||||
// AppendSliceValue implements the flag.Value interface and allows multiple
|
||||
// calls to the same variable to append a list.
|
||||
type AppendSliceValue []string
|
||||
|
||||
func (s *AppendSliceValue) String() string {
|
||||
return strings.Join(*s, ",")
|
||||
}
|
||||
|
||||
func (s *AppendSliceValue) Set(value string) error {
|
||||
if *s == nil {
|
||||
*s = make([]string, 0, 1)
|
||||
}
|
||||
|
||||
*s = append(*s, value)
|
||||
return nil
|
||||
}
|
||||
107
vendor/github.com/containous/go-bindata/go-bindata/main.go
generated
vendored
Normal file
107
vendor/github.com/containous/go-bindata/go-bindata/main.go
generated
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
|
||||
// license. Its contents can be found at:
|
||||
// http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/containous/go-bindata"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cfg := parseArgs()
|
||||
err := bindata.Translate(cfg)
|
||||
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "bindata: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// parseArgs create s a new, filled configuration instance
|
||||
// by reading and parsing command line options.
|
||||
//
|
||||
// This function exits the program with an error, if
|
||||
// any of the command line options are incorrect.
|
||||
func parseArgs() *bindata.Config {
|
||||
var version bool
|
||||
|
||||
c := bindata.NewConfig()
|
||||
|
||||
flag.Usage = func() {
|
||||
fmt.Printf("Usage: %s [options] <input directories>\n\n", os.Args[0])
|
||||
flag.PrintDefaults()
|
||||
}
|
||||
|
||||
flag.BoolVar(&c.Debug, "debug", c.Debug, "Do not embed the assets, but provide the embedding API. Contents will still be loaded from disk.")
|
||||
flag.BoolVar(&c.Dev, "dev", c.Dev, "Similar to debug, but does not emit absolute paths. Expects a rootDir variable to already exist in the generated code's package.")
|
||||
flag.StringVar(&c.Tags, "tags", c.Tags, "Optional set of build tags to include.")
|
||||
flag.StringVar(&c.Prefix, "prefix", c.Prefix, "Optional path prefix to strip off asset names.")
|
||||
flag.StringVar(&c.Package, "pkg", c.Package, "Package name to use in the generated code.")
|
||||
flag.BoolVar(&c.NoMemCopy, "nomemcopy", c.NoMemCopy, "Use a .rodata hack to get rid of unnecessary memcopies. Refer to the documentation to see what implications this carries.")
|
||||
flag.BoolVar(&c.NoCompress, "nocompress", c.NoCompress, "Assets will *not* be GZIP compressed when this flag is specified.")
|
||||
flag.BoolVar(&c.NoMetadata, "nometadata", c.NoMetadata, "Assets will not preserve size, mode, and modtime info.")
|
||||
flag.UintVar(&c.Mode, "mode", c.Mode, "Optional file mode override for all files.")
|
||||
flag.Int64Var(&c.ModTime, "modtime", c.ModTime, "Optional modification unix timestamp override for all files.")
|
||||
flag.StringVar(&c.Output, "o", c.Output, "Optional name of the output file to be generated.")
|
||||
flag.BoolVar(&version, "version", false, "Displays version information.")
|
||||
|
||||
ignore := make([]string, 0)
|
||||
flag.Var((*AppendSliceValue)(&ignore), "ignore", "Regex pattern to ignore")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
patterns := make([]*regexp.Regexp, 0)
|
||||
for _, pattern := range ignore {
|
||||
patterns = append(patterns, regexp.MustCompile(pattern))
|
||||
}
|
||||
c.Ignore = patterns
|
||||
|
||||
if version {
|
||||
fmt.Printf("%s\n", Version())
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
// Make sure we have input paths.
|
||||
if flag.NArg() == 0 {
|
||||
fmt.Fprintf(os.Stderr, "Missing <input dir>\n\n")
|
||||
flag.Usage()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Create input configurations.
|
||||
c.Input = make([]bindata.InputConfig, flag.NArg())
|
||||
for i := range c.Input {
|
||||
c.Input[i] = parseInput(flag.Arg(i))
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
// parseRecursive determines whether the given path has a recrusive indicator and
|
||||
// returns a new path with the recursive indicator chopped off if it does.
|
||||
//
|
||||
// ex:
|
||||
// /path/to/foo/... -> (/path/to/foo, true)
|
||||
// /path/to/bar -> (/path/to/bar, false)
|
||||
func parseInput(path string) bindata.InputConfig {
|
||||
if strings.HasSuffix(path, "/...") {
|
||||
return bindata.InputConfig{
|
||||
Path: filepath.Clean(path[:len(path)-4]),
|
||||
Recursive: true,
|
||||
}
|
||||
} else {
|
||||
return bindata.InputConfig{
|
||||
Path: filepath.Clean(path),
|
||||
Recursive: false,
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
19
vendor/github.com/containous/go-bindata/go-bindata/version.go
generated
vendored
Normal file
19
vendor/github.com/containous/go-bindata/go-bindata/version.go
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
|
||||
// license. Its contents can be found at:
|
||||
// http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
const AppName = "go-bindata"
|
||||
|
||||
var AppVersion = "dev"
|
||||
|
||||
func Version() string {
|
||||
return fmt.Sprintf("%s %s (Go runtime %s).\nCopyright (c) 2010-2013, Jim Teeuwen.",
|
||||
AppName, AppVersion, runtime.Version())
|
||||
}
|
||||
387
vendor/github.com/containous/go-bindata/release.go
generated
vendored
Normal file
387
vendor/github.com/containous/go-bindata/release.go
generated
vendored
Normal file
@@ -0,0 +1,387 @@
|
||||
// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
|
||||
// license. Its contents can be found at:
|
||||
// http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
package bindata
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// writeRelease writes the release code file.
|
||||
func writeRelease(w io.Writer, c *Config, toc []Asset) error {
|
||||
err := writeReleaseHeader(w, c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i := range toc {
|
||||
err = writeReleaseAsset(w, c, &toc[i])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// writeReleaseHeader writes output file headers.
|
||||
// This targets release builds.
|
||||
func writeReleaseHeader(w io.Writer, c *Config) error {
|
||||
var err error
|
||||
if c.NoCompress {
|
||||
if c.NoMemCopy {
|
||||
err = header_uncompressed_nomemcopy(w)
|
||||
} else {
|
||||
err = header_uncompressed_memcopy(w)
|
||||
}
|
||||
} else {
|
||||
if c.NoMemCopy {
|
||||
err = header_compressed_nomemcopy(w)
|
||||
} else {
|
||||
err = header_compressed_memcopy(w)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return header_release_common(w)
|
||||
}
|
||||
|
||||
// writeReleaseAsset write a release entry for the given asset.
|
||||
// A release entry is a function which embeds and returns
|
||||
// the file's byte content.
|
||||
func writeReleaseAsset(w io.Writer, c *Config, asset *Asset) error {
|
||||
fd, err := os.Open(asset.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer fd.Close()
|
||||
|
||||
if c.NoCompress {
|
||||
if c.NoMemCopy {
|
||||
err = uncompressed_nomemcopy(w, asset, fd)
|
||||
} else {
|
||||
err = uncompressed_memcopy(w, asset, fd)
|
||||
}
|
||||
} else {
|
||||
if c.NoMemCopy {
|
||||
err = compressed_nomemcopy(w, asset, fd)
|
||||
} else {
|
||||
err = compressed_memcopy(w, asset, fd)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return asset_release_common(w, c, asset)
|
||||
}
|
||||
|
||||
// sanitize prepares a valid UTF-8 string as a raw string constant.
|
||||
// Based on https://code.google.com/p/go/source/browse/godoc/static/makestatic.go?repo=tools
|
||||
func sanitize(b []byte) []byte {
|
||||
// Replace ` with `+"`"+`
|
||||
b = bytes.Replace(b, []byte("`"), []byte("`+\"`\"+`"), -1)
|
||||
|
||||
// Replace BOM with `+"\xEF\xBB\xBF"+`
|
||||
// (A BOM is valid UTF-8 but not permitted in Go source files.
|
||||
// I wouldn't bother handling this, but for some insane reason
|
||||
// jquery.js has a BOM somewhere in the middle.)
|
||||
return bytes.Replace(b, []byte("\xEF\xBB\xBF"), []byte("`+\"\\xEF\\xBB\\xBF\"+`"), -1)
|
||||
}
|
||||
|
||||
func header_compressed_nomemcopy(w io.Writer) error {
|
||||
_, err := fmt.Fprintf(w, `import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func bindataRead(data, name string) ([]byte, error) {
|
||||
gz, err := gzip.NewReader(strings.NewReader(data))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Read %%q: %%v", name, err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
_, err = io.Copy(&buf, gz)
|
||||
clErr := gz.Close()
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Read %%q: %%v", name, err)
|
||||
}
|
||||
if clErr != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
`)
|
||||
return err
|
||||
}
|
||||
|
||||
func header_compressed_memcopy(w io.Writer) error {
|
||||
_, err := fmt.Fprintf(w, `import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func bindataRead(data []byte, name string) ([]byte, error) {
|
||||
gz, err := gzip.NewReader(bytes.NewBuffer(data))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Read %%q: %%v", name, err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
_, err = io.Copy(&buf, gz)
|
||||
clErr := gz.Close()
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Read %%q: %%v", name, err)
|
||||
}
|
||||
if clErr != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
`)
|
||||
return err
|
||||
}
|
||||
|
||||
func header_uncompressed_nomemcopy(w io.Writer) error {
|
||||
_, err := fmt.Fprintf(w, `import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func bindataRead(data, name string) ([]byte, error) {
|
||||
var empty [0]byte
|
||||
sx := (*reflect.StringHeader)(unsafe.Pointer(&data))
|
||||
b := empty[:]
|
||||
bx := (*reflect.SliceHeader)(unsafe.Pointer(&b))
|
||||
bx.Data = sx.Data
|
||||
bx.Len = len(data)
|
||||
bx.Cap = bx.Len
|
||||
return b, nil
|
||||
}
|
||||
|
||||
`)
|
||||
return err
|
||||
}
|
||||
|
||||
func header_uncompressed_memcopy(w io.Writer) error {
|
||||
_, err := fmt.Fprintf(w, `import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
`)
|
||||
return err
|
||||
}
|
||||
|
||||
func header_release_common(w io.Writer) error {
|
||||
_, err := fmt.Fprintf(w, `type asset struct {
|
||||
bytes []byte
|
||||
info os.FileInfo
|
||||
}
|
||||
|
||||
type bindataFileInfo struct {
|
||||
name string
|
||||
size int64
|
||||
mode os.FileMode
|
||||
modTime time.Time
|
||||
}
|
||||
|
||||
func (fi bindataFileInfo) Name() string {
|
||||
return fi.name
|
||||
}
|
||||
func (fi bindataFileInfo) Size() int64 {
|
||||
return fi.size
|
||||
}
|
||||
func (fi bindataFileInfo) Mode() os.FileMode {
|
||||
return fi.mode
|
||||
}
|
||||
func (fi bindataFileInfo) ModTime() time.Time {
|
||||
return fi.modTime
|
||||
}
|
||||
func (fi bindataFileInfo) IsDir() bool {
|
||||
return false
|
||||
}
|
||||
func (fi bindataFileInfo) Sys() interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
`)
|
||||
return err
|
||||
}
|
||||
|
||||
func compressed_nomemcopy(w io.Writer, asset *Asset, r io.Reader) error {
|
||||
_, err := fmt.Fprintf(w, `var _%s = "`, asset.Func)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
gz := gzip.NewWriter(&StringWriter{Writer: w})
|
||||
_, err = io.Copy(gz, r)
|
||||
gz.Close()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = fmt.Fprintf(w, `"
|
||||
|
||||
func %sBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_%s,
|
||||
%q,
|
||||
)
|
||||
}
|
||||
|
||||
`, asset.Func, asset.Func, asset.Name)
|
||||
return err
|
||||
}
|
||||
|
||||
func compressed_memcopy(w io.Writer, asset *Asset, r io.Reader) error {
|
||||
_, err := fmt.Fprintf(w, `var _%s = []byte("`, asset.Func)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
gz := gzip.NewWriter(&StringWriter{Writer: w})
|
||||
_, err = io.Copy(gz, r)
|
||||
gz.Close()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = fmt.Fprintf(w, `")
|
||||
|
||||
func %sBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_%s,
|
||||
%q,
|
||||
)
|
||||
}
|
||||
|
||||
`, asset.Func, asset.Func, asset.Name)
|
||||
return err
|
||||
}
|
||||
|
||||
func uncompressed_nomemcopy(w io.Writer, asset *Asset, r io.Reader) error {
|
||||
_, err := fmt.Fprintf(w, `var _%s = "`, asset.Func)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = io.Copy(&StringWriter{Writer: w}, r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = fmt.Fprintf(w, `"
|
||||
|
||||
func %sBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_%s,
|
||||
%q,
|
||||
)
|
||||
}
|
||||
|
||||
`, asset.Func, asset.Func, asset.Name)
|
||||
return err
|
||||
}
|
||||
|
||||
func uncompressed_memcopy(w io.Writer, asset *Asset, r io.Reader) error {
|
||||
_, err := fmt.Fprintf(w, `var _%s = []byte(`, asset.Func)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
b, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if utf8.Valid(b) && !bytes.Contains(b, []byte{0}) {
|
||||
fmt.Fprintf(w, "`%s`", sanitize(b))
|
||||
} else {
|
||||
fmt.Fprintf(w, "%+q", b)
|
||||
}
|
||||
|
||||
_, err = fmt.Fprintf(w, `)
|
||||
|
||||
func %sBytes() ([]byte, error) {
|
||||
return _%s, nil
|
||||
}
|
||||
|
||||
`, asset.Func, asset.Func)
|
||||
return err
|
||||
}
|
||||
|
||||
func asset_release_common(w io.Writer, c *Config, asset *Asset) error {
|
||||
fi, err := os.Stat(asset.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mode := uint(fi.Mode())
|
||||
modTime := fi.ModTime().Unix()
|
||||
size := fi.Size()
|
||||
if c.NoMetadata {
|
||||
mode = 0
|
||||
modTime = 0
|
||||
size = 0
|
||||
}
|
||||
if c.Mode > 0 {
|
||||
mode = uint(os.ModePerm) & c.Mode
|
||||
}
|
||||
if c.ModTime > 0 {
|
||||
modTime = c.ModTime
|
||||
}
|
||||
_, err = fmt.Fprintf(w, `func %s() (*asset, error) {
|
||||
bytes, err := %sBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: %q, size: %d, mode: os.FileMode(%d), modTime: time.Unix(%d, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
`, asset.Func, asset.Func, asset.Name, size, mode, modTime)
|
||||
return err
|
||||
}
|
||||
63
vendor/github.com/containous/go-bindata/restore.go
generated
vendored
Normal file
63
vendor/github.com/containous/go-bindata/restore.go
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
|
||||
// license. Its contents can be found at:
|
||||
// http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
package bindata
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
func writeRestore(w io.Writer) error {
|
||||
_, err := fmt.Fprintf(w, `
|
||||
// RestoreAsset restores an asset under the given directory
|
||||
func RestoreAsset(dir, name string) error {
|
||||
data, err := Asset(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
info, err := AssetInfo(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RestoreAssets restores an asset under the given directory recursively
|
||||
func RestoreAssets(dir, name string) error {
|
||||
children, err := AssetDir(name)
|
||||
// File
|
||||
if err != nil {
|
||||
return RestoreAsset(dir, name)
|
||||
}
|
||||
// Dir
|
||||
for _, child := range children {
|
||||
err = RestoreAssets(dir, filepath.Join(name, child))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func _filePath(dir, name string) string {
|
||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...)
|
||||
}
|
||||
|
||||
`)
|
||||
return err
|
||||
}
|
||||
36
vendor/github.com/containous/go-bindata/stringwriter.go
generated
vendored
Normal file
36
vendor/github.com/containous/go-bindata/stringwriter.go
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
|
||||
// license. Its contents can be found at:
|
||||
// http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
package bindata
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
const lowerHex = "0123456789abcdef"
|
||||
|
||||
type StringWriter struct {
|
||||
io.Writer
|
||||
c int
|
||||
}
|
||||
|
||||
func (w *StringWriter) Write(p []byte) (n int, err error) {
|
||||
if len(p) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
buf := []byte(`\x00`)
|
||||
var b byte
|
||||
|
||||
for n, b = range p {
|
||||
buf[2] = lowerHex[b/16]
|
||||
buf[3] = lowerHex[b%16]
|
||||
w.Writer.Write(buf)
|
||||
w.c++
|
||||
}
|
||||
|
||||
n++
|
||||
|
||||
return
|
||||
}
|
||||
230
vendor/github.com/containous/go-bindata/toc.go
generated
vendored
Normal file
230
vendor/github.com/containous/go-bindata/toc.go
generated
vendored
Normal file
@@ -0,0 +1,230 @@
|
||||
// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
|
||||
// license. Its contents can be found at:
|
||||
// http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
package bindata
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type assetTree struct {
|
||||
Asset Asset
|
||||
Children map[string]*assetTree
|
||||
}
|
||||
|
||||
func newAssetTree() *assetTree {
|
||||
tree := &assetTree{}
|
||||
tree.Children = make(map[string]*assetTree)
|
||||
return tree
|
||||
}
|
||||
|
||||
func (node *assetTree) child(name string) *assetTree {
|
||||
rv, ok := node.Children[name]
|
||||
if !ok {
|
||||
rv = newAssetTree()
|
||||
node.Children[name] = rv
|
||||
}
|
||||
return rv
|
||||
}
|
||||
|
||||
func (root *assetTree) Add(route []string, asset Asset) {
|
||||
for _, name := range route {
|
||||
root = root.child(name)
|
||||
}
|
||||
root.Asset = asset
|
||||
}
|
||||
|
||||
func ident(w io.Writer, n int) {
|
||||
for i := 0; i < n; i++ {
|
||||
w.Write([]byte{'\t'})
|
||||
}
|
||||
}
|
||||
|
||||
func (root *assetTree) funcOrNil() string {
|
||||
if root.Asset.Func == "" {
|
||||
return "nil"
|
||||
} else {
|
||||
return root.Asset.Func
|
||||
}
|
||||
}
|
||||
|
||||
func (root *assetTree) writeGoMap(w io.Writer, nident int) {
|
||||
fmt.Fprintf(w, "&bintree{%s, map[string]*bintree{", root.funcOrNil())
|
||||
|
||||
if len(root.Children) > 0 {
|
||||
io.WriteString(w, "\n")
|
||||
|
||||
// Sort to make output stable between invocations
|
||||
filenames := make([]string, len(root.Children))
|
||||
i := 0
|
||||
for filename := range root.Children {
|
||||
filenames[i] = filename
|
||||
i++
|
||||
}
|
||||
sort.Strings(filenames)
|
||||
|
||||
for _, p := range filenames {
|
||||
ident(w, nident+1)
|
||||
fmt.Fprintf(w, `"%s": `, p)
|
||||
root.Children[p].writeGoMap(w, nident+1)
|
||||
}
|
||||
ident(w, nident)
|
||||
}
|
||||
|
||||
io.WriteString(w, "}}")
|
||||
if nident > 0 {
|
||||
io.WriteString(w, ",")
|
||||
}
|
||||
io.WriteString(w, "\n")
|
||||
}
|
||||
|
||||
func (root *assetTree) WriteAsGoMap(w io.Writer) error {
|
||||
_, err := fmt.Fprint(w, `type bintree struct {
|
||||
Func func() (*asset, error)
|
||||
Children map[string]*bintree
|
||||
}
|
||||
var _bintree = `)
|
||||
root.writeGoMap(w, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
func writeTOCTree(w io.Writer, toc []Asset) error {
|
||||
_, err := fmt.Fprintf(w, `// AssetDir returns the file names below a certain
|
||||
// directory embedded in the file by go-bindata.
|
||||
// For example if you run go-bindata on data/... and data contains the
|
||||
// following hierarchy:
|
||||
// data/
|
||||
// foo.txt
|
||||
// img/
|
||||
// a.png
|
||||
// b.png
|
||||
// then AssetDir("data") would return []string{"foo.txt", "img"}
|
||||
// AssetDir("data/img") would return []string{"a.png", "b.png"}
|
||||
// AssetDir("foo.txt") and AssetDir("notexist") would return an error
|
||||
// AssetDir("") will return []string{"data"}.
|
||||
func AssetDir(name string) ([]string, error) {
|
||||
node := _bintree
|
||||
if len(name) != 0 {
|
||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
pathList := strings.Split(cannonicalName, "/")
|
||||
for _, p := range pathList {
|
||||
node = node.Children[p]
|
||||
if node == nil {
|
||||
return nil, fmt.Errorf("Asset %%s not found", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
if node.Func != nil {
|
||||
return nil, fmt.Errorf("Asset %%s not found", name)
|
||||
}
|
||||
rv := make([]string, 0, len(node.Children))
|
||||
for childName := range node.Children {
|
||||
rv = append(rv, childName)
|
||||
}
|
||||
return rv, nil
|
||||
}
|
||||
|
||||
`)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tree := newAssetTree()
|
||||
for i := range toc {
|
||||
pathList := strings.Split(toc[i].Name, "/")
|
||||
tree.Add(pathList, toc[i])
|
||||
}
|
||||
return tree.WriteAsGoMap(w)
|
||||
}
|
||||
|
||||
// writeTOC writes the table of contents file.
|
||||
func writeTOC(w io.Writer, toc []Asset) error {
|
||||
err := writeTOCHeader(w)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i := range toc {
|
||||
err = writeTOCAsset(w, &toc[i])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return writeTOCFooter(w)
|
||||
}
|
||||
|
||||
// writeTOCHeader writes the table of contents file header.
|
||||
func writeTOCHeader(w io.Writer) error {
|
||||
_, err := fmt.Fprintf(w, `// Asset loads and returns the asset for the given name.
|
||||
// It returns an error if the asset could not be found or
|
||||
// could not be loaded.
|
||||
func Asset(name string) ([]byte, error) {
|
||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
if f, ok := _bindata[cannonicalName]; ok {
|
||||
a, err := f()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Asset %%s can't read by error: %%v", name, err)
|
||||
}
|
||||
return a.bytes, nil
|
||||
}
|
||||
return nil, fmt.Errorf("Asset %%s not found", name)
|
||||
}
|
||||
|
||||
// MustAsset is like Asset but panics when Asset would return an error.
|
||||
// It simplifies safe initialization of global variables.
|
||||
func MustAsset(name string) []byte {
|
||||
a, err := Asset(name)
|
||||
if err != nil {
|
||||
panic("asset: Asset(" + name + "): " + err.Error())
|
||||
}
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
// AssetInfo loads and returns the asset info for the given name.
|
||||
// It returns an error if the asset could not be found or
|
||||
// could not be loaded.
|
||||
func AssetInfo(name string) (os.FileInfo, error) {
|
||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
if f, ok := _bindata[cannonicalName]; ok {
|
||||
a, err := f()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("AssetInfo %%s can't read by error: %%v", name, err)
|
||||
}
|
||||
return a.info, nil
|
||||
}
|
||||
return nil, fmt.Errorf("AssetInfo %%s not found", name)
|
||||
}
|
||||
|
||||
// AssetNames returns the names of the assets.
|
||||
func AssetNames() []string {
|
||||
names := make([]string, 0, len(_bindata))
|
||||
for name := range _bindata {
|
||||
names = append(names, name)
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
// _bindata is a table, holding each asset generator, mapped to its name.
|
||||
var _bindata = map[string]func() (*asset, error){
|
||||
`)
|
||||
return err
|
||||
}
|
||||
|
||||
// writeTOCAsset write a TOC entry for the given asset.
|
||||
func writeTOCAsset(w io.Writer, asset *Asset) error {
|
||||
_, err := fmt.Fprintf(w, "\t%q: %s,\n", asset.Name, asset.Func)
|
||||
return err
|
||||
}
|
||||
|
||||
// writeTOCFooter writes the table of contents file footer.
|
||||
func writeTOCFooter(w io.Writer) error {
|
||||
_, err := fmt.Fprintf(w, `}
|
||||
|
||||
`)
|
||||
return err
|
||||
}
|
||||
21
vendor/github.com/cpuguy83/go-md2man/v2/LICENSE.md
generated
vendored
Normal file
21
vendor/github.com/cpuguy83/go-md2man/v2/LICENSE.md
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Brian Goff
|
||||
|
||||
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.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user