This is an automated email from the ASF dual-hosted git repository.

kezhenxu94 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-eyes.git


The following commit(s) were added to refs/heads/main by this push:
     new 7fca702  feat: list files by git when possible (#133)
7fca702 is described below

commit 7fca702e2eac3a619c0a7a412c2023bb451ee1ef
Author: tison <[email protected]>
AuthorDate: Mon Sep 5 11:18:50 2022 +0800

    feat: list files by git when possible (#133)
---
 Makefile                 |   2 +-
 go.mod                   |  24 +++++--
 go.sum                   | 116 +++++++++++++++++++++++++++++----
 pkg/header/check.go      | 163 ++++++++++++++++++++++++++++++----------------
 pkg/header/check_test.go | 164 +++++++++++++++++------------------------------
 pkg/header/config.go     |  48 +++++++-------
 6 files changed, 318 insertions(+), 199 deletions(-)

diff --git a/Makefile b/Makefile
index c31c61d..ad551fe 100644
--- a/Makefile
+++ b/Makefile
@@ -41,7 +41,7 @@ RELEASE_SRC = skywalking-$(PROJECT)-$(VERSION)-src
 all: clean lint license test build
 
 $(GO_LINT):
-       curl -sfL 
https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh 
-s -- -b $(GO_PATH)/bin v1.46.2
+       curl -sfL 
https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh 
-s -- -b $(GO_PATH)/bin v1.49.0
 
 .PHONY: lint
 lint: $(GO_LINT)
diff --git a/go.mod b/go.mod
index ed67a92..42657c4 100644
--- a/go.mod
+++ b/go.mod
@@ -5,38 +5,52 @@ go 1.18
 require (
        github.com/Masterminds/sprig/v3 v3.2.2
        github.com/bmatcuk/doublestar/v2 v2.0.4
+       github.com/go-git/go-git/v5 v5.4.2
        github.com/google/go-github/v33 v33.0.0
        github.com/google/licensecheck v0.3.1
        github.com/sirupsen/logrus v1.8.1
        github.com/spf13/cobra v1.4.0
        github.com/stretchr/testify v1.7.0
-       golang.org/x/net v0.0.0-20220517181318-183a9ca12b87
+       golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b
        golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5
        golang.org/x/tools v0.1.10
-       gopkg.in/yaml.v3 v3.0.0-20220512140231-539c8e751b99
+       gopkg.in/yaml.v3 v3.0.0
 )
 
 require (
        github.com/Masterminds/goutils v1.1.1 // indirect
        github.com/Masterminds/semver/v3 v3.1.1 // indirect
+       github.com/Microsoft/go-winio v0.5.2 // indirect
+       github.com/ProtonMail/go-crypto v0.0.0-20220824120805-4b6e5c587895 // 
indirect
+       github.com/acomagu/bufpipe v1.0.3 // indirect
+       github.com/cloudflare/circl v1.2.0 // indirect
        github.com/davecgh/go-spew v1.1.1 // indirect
+       github.com/emirpasic/gods v1.18.1 // indirect
+       github.com/go-git/gcfg v1.5.0 // indirect
+       github.com/go-git/go-billy/v5 v5.3.1 // indirect
        github.com/golang/protobuf v1.5.2 // indirect
        github.com/google/go-querystring v1.1.0 // indirect
        github.com/google/uuid v1.1.1 // indirect
        github.com/huandu/xstrings v1.3.1 // indirect
-       github.com/imdario/mergo v0.3.11 // indirect
+       github.com/imdario/mergo v0.3.13 // indirect
        github.com/inconshreveable/mousetrap v1.0.0 // indirect
+       github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // 
indirect
+       github.com/kevinburke/ssh_config v1.2.0 // indirect
        github.com/mitchellh/copystructure v1.0.0 // indirect
+       github.com/mitchellh/go-homedir v1.1.0 // indirect
        github.com/mitchellh/reflectwalk v1.0.0 // indirect
        github.com/pmezard/go-difflib v1.0.0 // indirect
+       github.com/sergi/go-diff v1.2.0 // indirect
        github.com/shopspring/decimal v1.2.0 // indirect
        github.com/spf13/cast v1.3.1 // indirect
        github.com/spf13/pflag v1.0.5 // indirect
-       golang.org/x/crypto v0.0.0-20220518034528-6f7dac969898 // indirect
+       github.com/xanzy/ssh-agent v0.3.2 // indirect
+       golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 // indirect
        golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect
-       golang.org/x/sys v0.0.0-20220517195934-5e4e11fc645e // indirect
+       golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 // indirect
        golang.org/x/text v0.3.7 // indirect
        golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df // indirect
        google.golang.org/appengine v1.6.7 // indirect
        google.golang.org/protobuf v1.28.0 // indirect
+       gopkg.in/warnings.v0 v0.1.2 // indirect
 )
diff --git a/go.sum b/go.sum
index ecd047b..5b9244e 100644
--- a/go.sum
+++ b/go.sum
@@ -39,22 +39,56 @@ github.com/Masterminds/semver/v3 v3.1.1 
h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030I
 github.com/Masterminds/semver/v3 v3.1.1/go.mod 
h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
 github.com/Masterminds/sprig/v3 v3.2.2 
h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8=
 github.com/Masterminds/sprig/v3 v3.2.2/go.mod 
h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk=
+github.com/Microsoft/go-winio v0.4.14/go.mod 
h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
+github.com/Microsoft/go-winio v0.4.16/go.mod 
h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
+github.com/Microsoft/go-winio v0.5.2 
h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA=
+github.com/Microsoft/go-winio v0.5.2/go.mod 
h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
+github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod 
h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
+github.com/ProtonMail/go-crypto v0.0.0-20220824120805-4b6e5c587895 
h1:NsReiLpErIPzRrnogAXYwSoU7txA977LjDGrbkewJbg=
+github.com/ProtonMail/go-crypto v0.0.0-20220824120805-4b6e5c587895/go.mod 
h1:UBYPn8k0D56RtnR8RFQMjmh4KrZzWJ5o7Z9SYjossQ8=
+github.com/acomagu/bufpipe v1.0.3 
h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk=
+github.com/acomagu/bufpipe v1.0.3/go.mod 
h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
+github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 
h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
+github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod 
h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
+github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 
h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
+github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod 
h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
 github.com/bmatcuk/doublestar/v2 v2.0.4 
h1:6I6oUiT/sU27eE2OFcWqBhL1SwjyvQuOssxT4a1yidI=
 github.com/bmatcuk/doublestar/v2 v2.0.4/go.mod 
h1:QMmcs3H2AUQICWhfzLXz+IYln8lRQmTZRptLie8RgRw=
+github.com/bwesterb/go-ristretto v1.2.0/go.mod 
h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
+github.com/bwesterb/go-ristretto v1.2.1/go.mod 
h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod 
h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/chzyer/logex v1.1.10/go.mod 
h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
 github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod 
h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
 github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod 
h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
 github.com/client9/misspell v0.3.4/go.mod 
h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cloudflare/circl v1.1.0/go.mod 
h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I=
+github.com/cloudflare/circl v1.2.0 
h1:NheeISPSUcYftKlfrLuOo4T62FkmD4t4jviLfFFYaec=
+github.com/cloudflare/circl v1.2.0/go.mod 
h1:Ch2UgYr6ti2KTtlejELlROl0YIYj7SLjAC8M+INXlMk=
 github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod 
h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
 github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod 
h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
+github.com/creack/pty v1.1.9/go.mod 
h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 github.com/davecgh/go-spew v1.1.0/go.mod 
h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 
h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod 
h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/emirpasic/gods v1.12.0/go.mod 
h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
+github.com/emirpasic/gods v1.18.1 
h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
+github.com/emirpasic/gods v1.18.1/go.mod 
h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
 github.com/envoyproxy/go-control-plane v0.9.0/go.mod 
h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
 github.com/envoyproxy/go-control-plane 
v0.9.1-0.20191026205805-5f8ba28d4473/go.mod 
h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
 github.com/envoyproxy/go-control-plane v0.9.4/go.mod 
h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod 
h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod 
h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
+github.com/gliderlabs/ssh v0.2.2 
h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
+github.com/gliderlabs/ssh v0.2.2/go.mod 
h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
+github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
+github.com/go-git/gcfg v1.5.0/go.mod 
h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
+github.com/go-git/go-billy/v5 v5.2.0/go.mod 
h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
+github.com/go-git/go-billy/v5 v5.3.1 
h1:CPiOUAzKtMRvolEKw+bG1PLRpT7D3LIs3/3ey4Aiu34=
+github.com/go-git/go-billy/v5 v5.3.1/go.mod 
h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
+github.com/go-git/go-git-fixtures/v4 v4.2.1 
h1:n9gGL1Ct/yIw+nfsfr8s4+sbhT+Ncu2SubfXjIWgci8=
+github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod 
h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0=
+github.com/go-git/go-git/v5 v5.4.2 
h1:BXyZu9t0VkbiHtqrsvdq39UDhGJTl1h55VW6CSC4aY4=
+github.com/go-git/go-git/v5 v5.4.2/go.mod 
h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc=
 github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod 
h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod 
h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod 
h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@@ -123,29 +157,53 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod 
h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
 github.com/huandu/xstrings v1.3.1 
h1:4jgBlKK6tLKFvO8u5pmYjG91cqytmDCDvGh7ECVFfFs=
 github.com/huandu/xstrings v1.3.1/go.mod 
h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
 github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod 
h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
-github.com/imdario/mergo v0.3.11 
h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
 github.com/imdario/mergo v0.3.11/go.mod 
h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
+github.com/imdario/mergo v0.3.12/go.mod 
h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
+github.com/imdario/mergo v0.3.13 
h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk=
+github.com/imdario/mergo v0.3.13/go.mod 
h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg=
 github.com/inconshreveable/mousetrap v1.0.0 
h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
 github.com/inconshreveable/mousetrap v1.0.0/go.mod 
h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
+github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 
h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
+github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod 
h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
+github.com/jessevdk/go-flags v1.5.0/go.mod 
h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
 github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod 
h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
 github.com/jstemmer/go-junit-report v0.9.1/go.mod 
h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
+github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod 
h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
+github.com/kevinburke/ssh_config v1.2.0 
h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
+github.com/kevinburke/ssh_config v1.2.0/go.mod 
h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
 github.com/kisielk/gotool v1.0.0/go.mod 
h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod 
h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/kr/pretty v0.1.0/go.mod 
h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
+github.com/kr/pretty v0.2.1/go.mod 
h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
-github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
 github.com/kr/text v0.1.0/go.mod 
h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod 
h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A=
+github.com/matryer/is v1.2.0/go.mod 
h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
 github.com/mitchellh/copystructure v1.0.0 
h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
 github.com/mitchellh/copystructure v1.0.0/go.mod 
h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
+github.com/mitchellh/go-homedir v1.1.0 
h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
+github.com/mitchellh/go-homedir v1.1.0/go.mod 
h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
 github.com/mitchellh/reflectwalk v1.0.0 
h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
 github.com/mitchellh/reflectwalk v1.0.0/go.mod 
h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod 
h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
+github.com/pkg/errors v0.8.1/go.mod 
h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.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/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod 
h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 github.com/rogpeppe/go-internal v1.3.0/go.mod 
h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
 github.com/russross/blackfriday/v2 v2.1.0/go.mod 
h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/sergi/go-diff v1.1.0/go.mod 
h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
+github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
+github.com/sergi/go-diff v1.2.0/go.mod 
h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
 github.com/shopspring/decimal v1.2.0 
h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
 github.com/shopspring/decimal v1.2.0/go.mod 
h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
+github.com/sirupsen/logrus v1.4.1/go.mod 
h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
+github.com/sirupsen/logrus v1.7.0/go.mod 
h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
 github.com/sirupsen/logrus v1.8.1 
h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
 github.com/sirupsen/logrus v1.8.1/go.mod 
h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
 github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
@@ -155,11 +213,15 @@ github.com/spf13/cobra v1.4.0/go.mod 
h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB
 github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
 github.com/spf13/pflag v1.0.5/go.mod 
h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
 github.com/stretchr/objx v0.1.0/go.mod 
h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.1.1/go.mod 
h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/testify v1.2.2/go.mod 
h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.4.0/go.mod 
h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
 github.com/stretchr/testify v1.5.1/go.mod 
h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
 github.com/stretchr/testify v1.7.0 
h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
 github.com/stretchr/testify v1.7.0/go.mod 
h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/xanzy/ssh-agent v0.3.0/go.mod 
h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
+github.com/xanzy/ssh-agent v0.3.2 
h1:eKj4SX2Fe7mui28ZgnFW5fmTz1EIr7ugo5s6wDxdHBM=
+github.com/xanzy/ssh-agent v0.3.2/go.mod 
h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
 github.com/yuin/goldmark v1.1.25/go.mod 
h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.1.27/go.mod 
h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.1.32/go.mod 
h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -168,14 +230,20 @@ go.opencensus.io v0.22.0/go.mod 
h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
 go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
 go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
 go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod 
h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod 
h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod 
h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod 
h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod 
h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod 
h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod 
h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20220518034528-6f7dac969898 
h1:SLP7Q4Di66FONjDJbCYrCRrh97focO6sLogHO7/g8F0=
-golang.org/x/crypto v0.0.0-20220518034528-6f7dac969898/go.mod 
h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod 
h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
+golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod 
h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod 
h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod 
h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod 
h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 
h1:Y/gsMcFOcR+6S6f3YeMKl5g+dZMEWqcz5Czj/GWYbkM=
+golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod 
h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod 
h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod 
h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod 
h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -234,9 +302,12 @@ golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod 
h1:qpuaurCH72eLCgpAm/
 golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod 
h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod 
h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod 
h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod 
h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod 
h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod 
h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod 
h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.0.0-20220517181318-183a9ca12b87 
h1:cCR+9mKLOGyX4Zx+uBZDXEDAQsvKQ/XbW4vreG5v1jU=
-golang.org/x/net v0.0.0-20220517181318-183a9ca12b87/go.mod 
h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
+golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b 
h1:ZmngSVLe/wycRns9MKikG9OWIEjGcGAkacif7oYQaUY=
+golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod 
h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod 
h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod 
h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod 
h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -253,6 +324,7 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod 
h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod 
h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod 
h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod 
h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod 
h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod 
h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod 
h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod 
h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -261,6 +333,7 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod 
h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod 
h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod 
h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod 
h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod 
h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod 
h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod 
h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod 
h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -278,16 +351,28 @@ golang.org/x/sys 
v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod 
h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod 
h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod 
h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod 
h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod 
h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod 
h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod 
h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod 
h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod 
h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod 
h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod 
h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod 
h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220517195934-5e4e11fc645e 
h1:w36l2Uw3dRan1K3TyXriXvY+6T56GNmlKGcqiQUJDfM=
-golang.org/x/sys v0.0.0-20220517195934-5e4e11fc645e/go.mod 
h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86/go.mod 
h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod 
h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 
h1:v6hYoSR9T5oet+pMXwUWkbiVqx/63mlHjefrHmxwfeY=
+golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod 
h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod 
h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 
h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod 
h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod 
h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod 
h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod 
h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -421,16 +506,21 @@ google.golang.org/protobuf v1.26.0/go.mod 
h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
 google.golang.org/protobuf v1.28.0 
h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
 google.golang.org/protobuf v1.28.0/go.mod 
h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod 
h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 
h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod 
h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod 
h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod 
h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c 
h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod 
h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
 gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
+gopkg.in/warnings.v0 v0.1.2/go.mod 
h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod 
h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0-20220512140231-539c8e751b99 
h1:dbuHpmKjkDzSOMKAWl10QNlgaZUd3V1q99xc81tt2Kc=
-gopkg.in/yaml.v3 v3.0.0-20220512140231-539c8e751b99/go.mod 
h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0 h1:hjy8E9ON/egN1tAYqKb61G10WtihqetD4sz2H+8nIeA=
+gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod 
h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod 
h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod 
h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/pkg/header/check.go b/pkg/header/check.go
index 209c741..e930001 100644
--- a/pkg/header/check.go
+++ b/pkg/header/check.go
@@ -18,6 +18,8 @@
 package header
 
 import (
+       "errors"
+       "io/fs"
        "net/http"
        "os"
        "path/filepath"
@@ -28,12 +30,21 @@ import (
        lcs "github.com/apache/skywalking-eyes/pkg/license"
 
        "github.com/bmatcuk/doublestar/v2"
+       "github.com/go-git/go-billy/v5/osfs"
+       "github.com/go-git/go-git/v5"
+       "github.com/go-git/go-git/v5/plumbing/format/gitignore"
+       "github.com/go-git/go-git/v5/plumbing/object"
 )
 
 // Check checks the license headers of the specified paths/globs.
 func Check(config *ConfigHeader, result *Result) error {
-       for _, pattern := range config.Paths {
-               if err := checkPattern(pattern, result, config); err != nil {
+       fileList, err := listFiles(config)
+       if err != nil {
+               return err
+       }
+
+       for _, file := range fileList {
+               if err := CheckFile(file, config, result); err != nil {
                        return err
                }
        }
@@ -41,79 +52,123 @@ func Check(config *ConfigHeader, result *Result) error {
        return nil
 }
 
-var seen = make(map[string]bool)
+func listFiles(config *ConfigHeader) ([]string, error) {
+       var fileList []string
 
-func checkPattern(pattern string, result *Result, config *ConfigHeader) error {
-       paths, err := glob(pattern)
+       repo, err := git.PlainOpen("./")
 
-       if err != nil {
-               return err
-       }
+       if err != nil { // we're not in a Git workspace, fallback to glob paths
+               var localFileList []string
+               for _, pattern := range config.Paths {
+                       if pattern == "." {
+                               pattern = "./"
+                       }
+                       files, err := doublestar.Glob(pattern)
+                       if err != nil {
+                               return nil, err
+                       }
+                       localFileList = append(localFileList, files...)
+               }
+
+               seen := make(map[string]bool)
+               for _, file := range localFileList {
+                       files, err := walkFile(file, seen)
+                       if err != nil {
+                               return nil, err
+                       }
+                       fileList = append(fileList, files...)
+               }
+       } else {
+               var candidates []string
 
-       for _, path := range paths {
-               if yes, err := config.ShouldIgnore(path); yes || err != nil {
-                       result.Ignore(path)
-                       continue
+               t, _ := repo.Worktree()
+               if t.Excludes == nil {
+                       t.Excludes = make([]gitignore.Pattern, 0)
                }
-               if err := checkPath(path, result, config); err != nil {
-                       return err
+               if ignorePattens, err := 
gitignore.LoadGlobalPatterns(osfs.New("")); err == nil {
+                       t.Excludes = append(t.Excludes, ignorePattens...)
+               }
+               if ignorePattens, err := 
gitignore.LoadSystemPatterns(osfs.New("")); err == nil {
+                       t.Excludes = append(t.Excludes, ignorePattens...)
+               }
+               s, _ := t.Status()
+               for file := range s {
+                       candidates = append(candidates, file)
                }
-               seen[path] = true
-       }
 
-       return nil
-}
+               head, _ := repo.Head()
+               commit, _ := repo.CommitObject(head.Hash())
+               tree, err := commit.Tree()
+               if err != nil {
+                       return nil, err
+               }
+               if err := tree.Files().ForEach(func(file *object.File) error {
+                       if file == nil {
+                               return errors.New("file pointer is nil")
+                       }
+                       candidates = append(candidates, file.Name)
+                       return nil
+               }); err != nil {
+                       return nil, err
+               }
 
-func glob(pattern string) (matches []string, err error) {
-       if pattern == "." {
-               return doublestar.Glob("./")
+               seen := make(map[string]bool)
+               for _, file := range candidates {
+                       if !seen[file] {
+                               seen[file] = true
+                               _, err := os.Stat(file)
+                               if err == nil {
+                                       fileList = append(fileList, file)
+                               } else if !os.IsNotExist(err) {
+                                       return nil, err
+                               }
+                       }
+               }
        }
 
-       return doublestar.Glob(pattern)
+       return fileList, nil
 }
 
-func checkPath(path string, result *Result, config *ConfigHeader) error {
-       defer func() { seen[path] = true }()
+func walkFile(file string, seen map[string]bool) ([]string, error) {
+       var files []string
 
-       if seen[path] {
-               return nil
+       if seen[file] {
+               return files, nil
        }
-
-       if yes, err := config.ShouldIgnore(path); yes || err != nil {
-               return err
-       }
-
-       pathInfo, err := os.Stat(path)
-
-       if err != nil {
-               return err
-       }
-
-       switch mode := pathInfo.Mode(); {
-       case mode.IsDir():
-               if err := filepath.Walk(path, func(p string, info os.FileInfo, 
err error) error {
-                       if info.IsDir() {
-                               return nil
-                       }
-                       if p == path { // when p is symbolic link file, it 
causes infinite recursive calls
+       seen[file] = true
+
+       if stat, err := os.Stat(file); err == nil {
+               switch mode := stat.Mode(); {
+               case mode.IsRegular():
+                       files = append(files, file)
+               case mode.IsDir():
+                       err := filepath.Walk(file, func(path string, info 
fs.FileInfo, err error) error {
+                               if path == file {
+                                       // when path is symbolic link file, it 
causes infinite recursive calls
+                                       return nil
+                               }
+                               if seen[path] {
+                                       return nil
+                               }
+                               seen[path] = true
+                               if info.Mode().IsRegular() {
+                                       files = append(files, path)
+                               }
                                return nil
+                       })
+                       if err != nil {
+                               return files, err
                        }
-                       return checkPath(p, result, config)
-               }); err != nil {
-                       return err
                }
-       case mode.IsRegular():
-               return CheckFile(path, config, result)
        }
-       return nil
+
+       return files, nil
 }
 
-// CheckFile checks whether or not the file contains the configured license 
header.
+// CheckFile checks whether the file contains the configured license header.
 func CheckFile(file string, config *ConfigHeader, result *Result) error {
        if yes, err := config.ShouldIgnore(file); yes || err != nil {
-               if !seen[file] {
-                       result.Ignore(file)
-               }
+               result.Ignore(file)
                return err
        }
 
diff --git a/pkg/header/check_test.go b/pkg/header/check_test.go
index ca70f3a..6f1074d 100644
--- a/pkg/header/check_test.go
+++ b/pkg/header/check_test.go
@@ -18,125 +18,81 @@
 package header
 
 import (
-       "io/ioutil"
+       "os"
        "path/filepath"
        "strings"
        "testing"
 
+       "github.com/stretchr/testify/require"
        "gopkg.in/yaml.v3"
 )
 
-var c struct {
-       Header ConfigHeader `yaml:"header"`
-}
-
-func init() {
-       content, err := 
ioutil.ReadFile("../../test/testdata/.licenserc_for_test_check.yaml")
-       if err != nil {
-               panic(err)
-       }
-       if err := yaml.Unmarshal(content, &c); err != nil {
-               panic(err)
-       }
-       if err := c.Header.Finalize(); err != nil {
-               panic(err)
-       }
-}
-
 func TestCheckFile(t *testing.T) {
        type args struct {
-               name       string
-               file       string
-               result     *Result
-               wantErr    bool
-               hasFailure bool
+               name   string
+               file   string
+               result *Result
        }
-       tests := func() []args {
-               files, err := 
filepath.Glob("../../test/testdata/include_test/with_license/*")
-               if err != nil {
-                       t.Error(err)
-               }
 
-               var cases []args
-
-               for _, file := range files {
-                       cases = append(cases, args{
-                               name:       file,
-                               file:       file,
-                               result:     &Result{},
-                               wantErr:    false,
-                               hasFailure: false,
-                       })
-               }
-
-               return cases
-       }()
-
-       if len(tests) == 0 {
-               t.Errorf("Tests should not be empty")
+       var c struct {
+               Header ConfigHeader `yaml:"header"`
        }
 
-       for _, tt := range tests {
-               t.Run(tt.name, func(t *testing.T) {
-                       if strings.TrimSpace(c.Header.GetLicenseContent()) == 
"" {
-                               t.Errorf("License should not be empty")
-                       }
-                       if err := CheckFile(tt.file, &c.Header, tt.result); 
(err != nil) != tt.wantErr {
-                               t.Errorf("CheckFile() error = %v, wantErr %v", 
err, tt.wantErr)
-                       }
-                       if len(tt.result.Ignored) > 0 {
-                               t.Errorf("Should not ignore any file, %v", 
tt.result.Ignored)
-                       }
-                       if tt.result.HasFailure() != tt.hasFailure {
-                               t.Errorf("CheckFile() result has failure = %v, 
wanted = %v", tt.result.Failure, tt.hasFailure)
+       require.NoError(t, os.Chdir("../.."))
+       content, err := 
os.ReadFile("test/testdata/.licenserc_for_test_check.yaml")
+       require.NoError(t, err)
+       require.NoError(t, yaml.Unmarshal(content, &c))
+       require.NoError(t, c.Header.Finalize())
+
+       t.Run("WithLicense", func(t *testing.T) {
+               tests := func() []args {
+                       files, err := 
filepath.Glob("test/testdata/include_test/with_license/*")
+                       require.NoError(t, err)
+                       var cases []args
+                       for _, file := range files {
+                               cases = append(cases, args{
+                                       name:   file,
+                                       file:   file,
+                                       result: &Result{},
+                               })
                        }
-               })
-       }
-}
-
-func TestCheckFileFailure(t *testing.T) {
-       type args struct {
-               name       string
-               file       string
-               result     *Result
-               wantErr    bool
-               hasFailure bool
-       }
-       tests := func() []args {
-               files, err := 
filepath.Glob("../../test/testdata/include_test/without_license/*")
-               if err != nil {
-                       panic(err)
-               }
-
-               var cases []args
-
-               for _, file := range files {
-                       cases = append(cases, args{
-                               name:       file,
-                               file:       file,
-                               result:     &Result{},
-                               wantErr:    false,
-                               hasFailure: true,
+                       return cases
+               }()
+               require.NotEmpty(t, tests)
+
+               for _, tt := range tests {
+                       t.Run(tt.name, func(t *testing.T) {
+                               require.NotEmpty(t, 
strings.TrimSpace(c.Header.GetLicenseContent()))
+                               require.NoError(t, CheckFile(tt.file, 
&c.Header, tt.result))
+                               require.Len(t, tt.result.Ignored, 0)
+                               require.False(t, tt.result.HasFailure())
                        })
                }
-
-               return cases
-       }()
-
-       for _, tt := range tests {
-               t.Run(tt.name, func(t *testing.T) {
-                       if strings.TrimSpace(c.Header.GetLicenseContent()) == 
"" {
-                               t.Errorf("License should not be empty")
-                       }
-                       if err := CheckFile(tt.file, &c.Header, tt.result); 
(err != nil) != tt.wantErr {
-                               t.Errorf("CheckFile() error = %v, wantErr %v", 
err, tt.wantErr)
-                       }
-                       if len(tt.result.Ignored) > 0 {
-                               t.Errorf("Should not ignore any file, %v", 
tt.result.Ignored)
+       })
+
+       t.Run("WithoutLicense", func(t *testing.T) {
+               tests := func() []args {
+                       files, err := 
filepath.Glob("test/testdata/include_test/without_license/*")
+                       require.NoError(t, err)
+                       var cases []args
+                       for _, file := range files {
+                               cases = append(cases, args{
+                                       name:   file,
+                                       file:   file,
+                                       result: &Result{},
+                               })
                        }
-                       if tt.result.HasFailure() != tt.hasFailure {
-                               t.Errorf("CheckFile() result has failure = %v, 
wanted = %v", tt.result.Failure, tt.hasFailure)
-                       }
-               })
-       }
+                       return cases
+               }()
+               require.NotEmpty(t, tests)
+
+               for _, tt := range tests {
+                       t.Run(tt.name, func(t *testing.T) {
+                               require.NotEmpty(t, 
strings.TrimSpace(c.Header.GetLicenseContent()))
+                               require.NoError(t, CheckFile(tt.file, 
&c.Header, tt.result))
+                               require.Len(t, tt.result.Ignored, 0)
+                               require.True(t, tt.result.HasFailure())
+                       })
+               }
+       })
 }
diff --git a/pkg/header/config.go b/pkg/header/config.go
index 254eddb..c77b679 100644
--- a/pkg/header/config.go
+++ b/pkg/header/config.go
@@ -18,7 +18,6 @@
 package header
 
 import (
-       "bufio"
        "fmt"
        "os"
        "regexp"
@@ -116,16 +115,34 @@ func (config *ConfigHeader) NormalizedPattern() 
*regexp.Regexp {
 }
 
 func (config *ConfigHeader) ShouldIgnore(path string) (bool, error) {
-       for _, ignorePattern := range config.PathsIgnore {
-               if matched, err := doublestar.Match(ignorePattern, path); 
matched || err != nil {
-                       return matched, err
+       matched, err := tryMatchPatten(path, config.Paths)
+       if !matched || err != nil {
+               return !matched, err
+       }
+
+       ignored, err := tryMatchPatten(path, config.PathsIgnore)
+       if ignored || err != nil {
+               return ignored, err
+       }
+
+       return false, nil
+}
+
+func tryMatchPatten(path string, patterns []string) (bool, error) {
+       for _, pattern := range patterns {
+               if m, err := doublestar.Match(pattern, path); m || err != nil {
+                       return m, err
                }
        }
 
        if stat, err := os.Stat(path); err == nil {
-               for _, ignorePattern := range config.PathsIgnore {
-                       ignorePattern = strings.TrimRight(ignorePattern, "/")
-                       if strings.HasPrefix(path, ignorePattern+"/") || 
stat.Name() == ignorePattern {
+               for _, pattern := range patterns {
+                       pattern = strings.TrimRight(pattern, "/")
+                       if stat.Name() == pattern {
+                               return true, nil
+                       }
+                       pattern += "/"
+                       if strings.HasPrefix(path, pattern) {
                                return true, nil
                        }
                }
@@ -141,23 +158,10 @@ func (config *ConfigHeader) Finalize() error {
 
        comments.OverrideLanguageCommentStyle(config.Languages)
 
-       config.PathsIgnore = append(config.PathsIgnore, ".git", "**/*.txt")
-
-       if file, err := os.Open(".gitignore"); err == nil {
-               defer func() { _ = file.Close() }()
-
-               for scanner := bufio.NewScanner(file); scanner.Scan(); {
-                       line := scanner.Text()
-                       if strings.HasPrefix(line, "#") || 
strings.TrimSpace(line) == "" {
-                               continue
-                       }
-                       line = strings.TrimLeft(line, "/")
-                       logger.Log.Debugln("Add ignore path from .gitignore:", 
line)
-                       config.PathsIgnore = append(config.PathsIgnore, 
strings.TrimSpace(line))
-               }
-       }
+       config.PathsIgnore = append(config.PathsIgnore, "**/*.txt")
 
        logger.Log.Debugln("License header is:", config.NormalizedLicense())
+
        if p := config.NormalizedPattern(); p != nil {
                logger.Log.Debugln("Pattern is:", p)
        }

Reply via email to