Bump github.com/go-git/go-git/v5 from 5.11.0 to 5.12.0

Bumps [github.com/go-git/go-git/v5](https://github.com/go-git/go-git) from 5.11.0 to 5.12.0.
- [Release notes](https://github.com/go-git/go-git/releases)
- [Commits](https://github.com/go-git/go-git/compare/v5.11.0...v5.12.0)

---
updated-dependencies:
- dependency-name: github.com/go-git/go-git/v5
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
This commit is contained in:
dependabot[bot]
2024-04-01 20:14:43 +00:00
committed by GitHub
parent 652e420618
commit c2177012f9
44 changed files with 1047 additions and 477 deletions
+8 -8
View File
@@ -3,19 +3,19 @@ module github.com/actions/actions-sync
go 1.21 go 1.21
require ( require (
github.com/go-git/go-git/v5 v5.11.0 github.com/go-git/go-git/v5 v5.12.0
github.com/google/go-github/v43 v43.0.0 github.com/google/go-github/v43 v43.0.0
github.com/gorilla/mux v1.8.1 github.com/gorilla/mux v1.8.1
github.com/pkg/errors v0.9.1 github.com/pkg/errors v0.9.1
github.com/spf13/cobra v1.8.0 github.com/spf13/cobra v1.8.0
github.com/stretchr/testify v1.8.4 github.com/stretchr/testify v1.9.0
golang.org/x/oauth2 v0.17.0 golang.org/x/oauth2 v0.17.0
) )
require ( require (
dario.cat/mergo v1.0.0 // indirect dario.cat/mergo v1.0.0 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect github.com/ProtonMail/go-crypto v1.0.0 // indirect
github.com/cloudflare/circl v1.3.7 // indirect github.com/cloudflare/circl v1.3.7 // indirect
github.com/cyphar/filepath-securejoin v0.2.4 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
@@ -30,14 +30,14 @@ require (
github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/sergi/go-diff v1.2.0 // indirect github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
github.com/skeema/knownhosts v1.2.1 // indirect github.com/skeema/knownhosts v1.2.2 // indirect
github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/pflag v1.0.5 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect
golang.org/x/crypto v0.19.0 // indirect golang.org/x/crypto v0.21.0 // indirect
golang.org/x/mod v0.12.0 // indirect golang.org/x/mod v0.12.0 // indirect
golang.org/x/net v0.21.0 // indirect golang.org/x/net v0.22.0 // indirect
golang.org/x/sys v0.17.0 // indirect golang.org/x/sys v0.18.0 // indirect
golang.org/x/tools v0.13.0 // indirect golang.org/x/tools v0.13.0 // indirect
google.golang.org/appengine v1.6.7 // indirect google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.31.0 // indirect google.golang.org/protobuf v1.31.0 // indirect
+21 -21
View File
@@ -3,8 +3,8 @@ dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg= github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78=
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
@@ -23,16 +23,16 @@ github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcej
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE=
github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4= github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU=
github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
github.com/go-git/go-git/v5 v5.11.0 h1:XIZc1p+8YzypNr34itUfSvYJcv+eYdTnTvOZ2vD3cA4= github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys=
github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY= github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -73,11 +73,11 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ= github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A=
github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo=
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
@@ -85,8 +85,8 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 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.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
@@ -95,8 +95,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
@@ -109,8 +109,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ= golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ=
golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA= golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -131,15 +131,15 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/text v0.3.0/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.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 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.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -171,6 +171,6 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= 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.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.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+3 -1
View File
@@ -73,7 +73,9 @@ func (c *x448) GenerateECDH(rand io.Reader) (point []byte, secret []byte, err er
func (c *x448) Encaps(rand io.Reader, point []byte) (ephemeral, sharedSecret []byte, err error) { func (c *x448) Encaps(rand io.Reader, point []byte) (ephemeral, sharedSecret []byte, err error) {
var pk, ss x448lib.Key var pk, ss x448lib.Key
seed, e, err := c.generateKeyPairBytes(rand) seed, e, err := c.generateKeyPairBytes(rand)
if err != nil {
return nil, nil, err
}
copy(pk[:], point) copy(pk[:], point)
x448lib.Shared(&ss, &seed, &pk) x448lib.Shared(&ss, &seed, &pk)
+2 -2
View File
@@ -28,10 +28,10 @@ compatibility status with go-git.
## Branching and merging ## Branching and merging
| Feature | Sub-feature | Status | Notes | Examples | | Feature | Sub-feature | Status | Notes | Examples |
| ----------- | ----------- | ------ | --------------------------------------- | ----------------------------------------------------------------------------------------------- | | ----------- | ----------- | ------------ | --------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `branch` | | ✅ | | - [branch](_examples/branch/main.go) | | `branch` | | ✅ | | - [branch](_examples/branch/main.go) |
| `checkout` | | ✅ | Basic usages of checkout are supported. | - [checkout](_examples/checkout/main.go) | | `checkout` | | ✅ | Basic usages of checkout are supported. | - [checkout](_examples/checkout/main.go) |
| `merge` | | ❌ | | | | `merge` | | ⚠️ (partial) | Fast-forward only | |
| `mergetool` | | ❌ | | | | `mergetool` | | ❌ | | |
| `stash` | | ❌ | | | | `stash` | | ❌ | | |
| `tag` | | ✅ | | - [tag](_examples/tag/main.go) <br/> - [tag create and push](_examples/tag-create-push/main.go) | | `tag` | | ✅ | | - [tag](_examples/tag/main.go) <br/> - [tag create and push](_examples/tag-create-push/main.go) |
+1
View File
@@ -28,6 +28,7 @@ build-git:
test: test:
@echo "running against `git version`"; \ @echo "running against `git version`"; \
$(GOTEST) -race ./... $(GOTEST) -race ./...
$(GOTEST) -v _examples/common_test.go _examples/common.go --examples
TEMP_REPO := $(shell mktemp) TEMP_REPO := $(shell mktemp)
test-sha256: test-sha256:
+40 -4
View File
@@ -89,6 +89,25 @@ type CloneOptions struct {
Shared bool Shared bool
} }
// MergeOptions describes how a merge should be performed.
type MergeOptions struct {
// Strategy defines the merge strategy to be used.
Strategy MergeStrategy
}
// MergeStrategy represents the different types of merge strategies.
type MergeStrategy int8
const (
// FastForwardMerge represents a Git merge strategy where the current
// branch can be simply updated to point to the HEAD of the branch being
// merged. This is only possible if the history of the branch being merged
// is a linear descendant of the current branch, with no conflicting commits.
//
// This is the default option.
FastForwardMerge MergeStrategy = iota
)
// Validate validates the fields and sets the default values. // Validate validates the fields and sets the default values.
func (o *CloneOptions) Validate() error { func (o *CloneOptions) Validate() error {
if o.URL == "" { if o.URL == "" {
@@ -166,7 +185,7 @@ const (
// AllTags fetch all tags from the remote (i.e., fetch remote tags // AllTags fetch all tags from the remote (i.e., fetch remote tags
// refs/tags/* into local tags with the same name) // refs/tags/* into local tags with the same name)
AllTags AllTags
//NoTags fetch no tags from the remote at all // NoTags fetch no tags from the remote at all
NoTags NoTags
) )
@@ -198,6 +217,9 @@ type FetchOptions struct {
CABundle []byte CABundle []byte
// ProxyOptions provides info required for connecting to a proxy. // ProxyOptions provides info required for connecting to a proxy.
ProxyOptions transport.ProxyOptions ProxyOptions transport.ProxyOptions
// Prune specify that local refs that match given RefSpecs and that do
// not exist remotely will be removed.
Prune bool
} }
// Validate validates the fields and sets the default values. // Validate validates the fields and sets the default values.
@@ -324,9 +346,9 @@ var (
// CheckoutOptions describes how a checkout operation should be performed. // CheckoutOptions describes how a checkout operation should be performed.
type CheckoutOptions struct { type CheckoutOptions struct {
// Hash is the hash of the commit to be checked out. If used, HEAD will be // Hash is the hash of a commit or tag to be checked out. If used, HEAD
// in detached mode. If Create is not used, Branch and Hash are mutually // will be in detached mode. If Create is not used, Branch and Hash are
// exclusive. // mutually exclusive.
Hash plumbing.Hash Hash plumbing.Hash
// Branch to be checked out, if Branch and Hash are empty is set to `master`. // Branch to be checked out, if Branch and Hash are empty is set to `master`.
Branch plumbing.ReferenceName Branch plumbing.ReferenceName
@@ -405,6 +427,11 @@ func (o *ResetOptions) Validate(r *Repository) error {
} }
o.Commit = ref.Hash() o.Commit = ref.Hash()
} else {
_, err := r.CommitObject(o.Commit)
if err != nil {
return fmt.Errorf("invalid reset option: %w", err)
}
} }
return nil return nil
@@ -474,6 +501,11 @@ type AddOptions struct {
// Glob adds all paths, matching pattern, to the index. If pattern matches a // Glob adds all paths, matching pattern, to the index. If pattern matches a
// directory path, all directory contents are added to the index recursively. // directory path, all directory contents are added to the index recursively.
Glob string Glob string
// SkipStatus adds the path with no status check. This option is relevant only
// when the `Path` option is specified and does not apply when the `All` option is used.
// Notice that when passing an ignored path it will be added anyway.
// When true it can speed up adding files to the worktree in very large repositories.
SkipStatus bool
} }
// Validate validates the fields and sets the default values. // Validate validates the fields and sets the default values.
@@ -507,6 +539,10 @@ type CommitOptions struct {
// commit will not be signed. The private key must be present and already // commit will not be signed. The private key must be present and already
// decrypted. // decrypted.
SignKey *openpgp.Entity SignKey *openpgp.Entity
// Signer denotes a cryptographic signer to sign the commit with.
// A nil value here means the commit will not be signed.
// Takes precedence over SignKey.
Signer Signer
// Amend will create a new commit object and replace the commit that HEAD currently // Amend will create a new commit object and replace the commit that HEAD currently
// points to. Cannot be used with All nor Parents. // points to. Cannot be used with All nor Parents.
Amend bool Amend bool
+2 -2
View File
@@ -116,7 +116,7 @@ func loadPatterns(fs billy.Filesystem, path string) (ps []Pattern, err error) {
return return
} }
// LoadGlobalPatterns loads gitignore patterns from from the gitignore file // LoadGlobalPatterns loads gitignore patterns from the gitignore file
// declared in a user's ~/.gitconfig file. If the ~/.gitconfig file does not // declared in a user's ~/.gitconfig file. If the ~/.gitconfig file does not
// exist the function will return nil. If the core.excludesfile property // exist the function will return nil. If the core.excludesfile property
// is not declared, the function will return nil. If the file pointed to by // is not declared, the function will return nil. If the file pointed to by
@@ -132,7 +132,7 @@ func LoadGlobalPatterns(fs billy.Filesystem) (ps []Pattern, err error) {
return loadPatterns(fs, fs.Join(home, gitconfigFile)) return loadPatterns(fs, fs.Join(home, gitconfigFile))
} }
// LoadSystemPatterns loads gitignore patterns from from the gitignore file // LoadSystemPatterns loads gitignore patterns from the gitignore file
// declared in a system's /etc/gitconfig file. If the /etc/gitconfig file does // declared in a system's /etc/gitconfig file. If the /etc/gitconfig file does
// not exist the function will return nil. If the core.excludesfile property // not exist the function will return nil. If the core.excludesfile property
// is not declared, the function will return nil. If the file pointed to by // is not declared, the function will return nil. If the file pointed to by
+3 -3
View File
@@ -27,7 +27,7 @@ const (
// the commit with the "mergetag" header. // the commit with the "mergetag" header.
headermergetag string = "mergetag" headermergetag string = "mergetag"
defaultUtf8CommitMesageEncoding MessageEncoding = "UTF-8" defaultUtf8CommitMessageEncoding MessageEncoding = "UTF-8"
) )
// Hash represents the hash of an object // Hash represents the hash of an object
@@ -189,7 +189,7 @@ func (c *Commit) Decode(o plumbing.EncodedObject) (err error) {
} }
c.Hash = o.Hash() c.Hash = o.Hash()
c.Encoding = defaultUtf8CommitMesageEncoding c.Encoding = defaultUtf8CommitMessageEncoding
reader, err := o.Reader() reader, err := o.Reader()
if err != nil { if err != nil {
@@ -335,7 +335,7 @@ func (c *Commit) encode(o plumbing.EncodedObject, includeSig bool) (err error) {
} }
} }
if string(c.Encoding) != "" && c.Encoding != defaultUtf8CommitMesageEncoding { if string(c.Encoding) != "" && c.Encoding != defaultUtf8CommitMessageEncoding {
if _, err = fmt.Fprintf(w, "\n%s %s", headerencoding, c.Encoding); err != nil { if _, err = fmt.Fprintf(w, "\n%s %s", headerencoding, c.Encoding); err != nil {
return err return err
} }
+11 -4
View File
@@ -57,6 +57,8 @@ func (c *commitPathIter) Next() (*Commit, error) {
} }
func (c *commitPathIter) getNextFileCommit() (*Commit, error) { func (c *commitPathIter) getNextFileCommit() (*Commit, error) {
var parentTree, currentTree *Tree
for { for {
// Parent-commit can be nil if the current-commit is the initial commit // Parent-commit can be nil if the current-commit is the initial commit
parentCommit, parentCommitErr := c.sourceIter.Next() parentCommit, parentCommitErr := c.sourceIter.Next()
@@ -68,13 +70,17 @@ func (c *commitPathIter) getNextFileCommit() (*Commit, error) {
parentCommit = nil parentCommit = nil
} }
// Fetch the trees of the current and parent commits if parentTree == nil {
currentTree, currTreeErr := c.currentCommit.Tree() var currTreeErr error
currentTree, currTreeErr = c.currentCommit.Tree()
if currTreeErr != nil { if currTreeErr != nil {
return nil, currTreeErr return nil, currTreeErr
} }
} else {
currentTree = parentTree
parentTree = nil
}
var parentTree *Tree
if parentCommit != nil { if parentCommit != nil {
var parentTreeErr error var parentTreeErr error
parentTree, parentTreeErr = parentCommit.Tree() parentTree, parentTreeErr = parentCommit.Tree()
@@ -115,7 +121,8 @@ func (c *commitPathIter) hasFileChange(changes Changes, parent *Commit) bool {
// filename matches, now check if source iterator contains all commits (from all refs) // filename matches, now check if source iterator contains all commits (from all refs)
if c.checkParent { if c.checkParent {
if parent != nil && isParentHash(parent.Hash, c.currentCommit) { // Check if parent is beyond the initial commit
if parent == nil || isParentHash(parent.Hash, c.currentCommit) {
return true return true
} }
continue continue
+41 -54
View File
@@ -6,7 +6,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"io" "io"
"math" "strconv"
"strings" "strings"
"github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing"
@@ -234,69 +234,56 @@ func (fileStats FileStats) String() string {
return printStat(fileStats) return printStat(fileStats)
} }
// printStat prints the stats of changes in content of files.
// Original implementation: https://github.com/git/git/blob/1a87c842ece327d03d08096395969aca5e0a6996/diff.c#L2615
// Parts of the output:
// <pad><filename><pad>|<pad><changeNumber><pad><+++/---><newline>
// example: " main.go | 10 +++++++--- "
func printStat(fileStats []FileStat) string { func printStat(fileStats []FileStat) string {
padLength := float64(len(" ")) maxGraphWidth := uint(53)
newlineLength := float64(len("\n")) maxNameLen := 0
separatorLength := float64(len("|")) maxChangeLen := 0
// Soft line length limit. The text length calculation below excludes
// length of the change number. Adding that would take it closer to 80, scaleLinear := func(it, width, max uint) uint {
// but probably not more than 80, until it's a huge number. if it == 0 || max == 0 {
lineLength := 72.0 return 0
}
return 1 + (it * (width - 1) / max)
}
// Get the longest filename and longest total change.
var longestLength float64
var longestTotalChange float64
for _, fs := range fileStats { for _, fs := range fileStats {
if int(longestLength) < len(fs.Name) { if len(fs.Name) > maxNameLen {
longestLength = float64(len(fs.Name)) maxNameLen = len(fs.Name)
} }
totalChange := fs.Addition + fs.Deletion
if int(longestTotalChange) < totalChange { changes := strconv.Itoa(fs.Addition + fs.Deletion)
longestTotalChange = float64(totalChange) if len(changes) > maxChangeLen {
maxChangeLen = len(changes)
} }
} }
// Parts of the output: result := ""
// <pad><filename><pad>|<pad><changeNumber><pad><+++/---><newline>
// example: " main.go | 10 +++++++--- "
// <pad><filename><pad>
leftTextLength := padLength + longestLength + padLength
// <pad><number><pad><+++++/-----><newline>
// Excluding number length here.
rightTextLength := padLength + padLength + newlineLength
totalTextArea := leftTextLength + separatorLength + rightTextLength
heightOfHistogram := lineLength - totalTextArea
// Scale the histogram.
var scaleFactor float64
if longestTotalChange > heightOfHistogram {
// Scale down to heightOfHistogram.
scaleFactor = longestTotalChange / heightOfHistogram
} else {
scaleFactor = 1.0
}
finalOutput := ""
for _, fs := range fileStats { for _, fs := range fileStats {
addn := float64(fs.Addition) add := uint(fs.Addition)
deln := float64(fs.Deletion) del := uint(fs.Deletion)
addc := int(math.Floor(addn/scaleFactor)) np := maxNameLen - len(fs.Name)
delc := int(math.Floor(deln/scaleFactor)) cp := maxChangeLen - len(strconv.Itoa(fs.Addition+fs.Deletion))
if addc < 0 {
addc = 0 total := add + del
} if total > maxGraphWidth {
if delc < 0 { add = scaleLinear(add, maxGraphWidth, total)
delc = 0 del = scaleLinear(del, maxGraphWidth, total)
}
adds := strings.Repeat("+", addc)
dels := strings.Repeat("-", delc)
finalOutput += fmt.Sprintf(" %s | %d %s%s\n", fs.Name, (fs.Addition + fs.Deletion), adds, dels)
} }
return finalOutput adds := strings.Repeat("+", int(add))
dels := strings.Repeat("-", int(del))
namePad := strings.Repeat(" ", np)
changePad := strings.Repeat(" ", cp)
result += fmt.Sprintf(" %s%s | %s%d %s%s\n", fs.Name, namePad, changePad, total, adds, dels)
}
return result
} }
func getFileStatsFromFilePatches(filePatches []fdiff.FilePatch) FileStats { func getFileStatsFromFilePatches(filePatches []fdiff.FilePatch) FileStats {
+32
View File
@@ -7,6 +7,7 @@ import (
"io" "io"
"path" "path"
"path/filepath" "path/filepath"
"sort"
"strings" "strings"
"github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing"
@@ -27,6 +28,7 @@ var (
ErrFileNotFound = errors.New("file not found") ErrFileNotFound = errors.New("file not found")
ErrDirectoryNotFound = errors.New("directory not found") ErrDirectoryNotFound = errors.New("directory not found")
ErrEntryNotFound = errors.New("entry not found") ErrEntryNotFound = errors.New("entry not found")
ErrEntriesNotSorted = errors.New("entries in tree are not sorted")
) )
// Tree is basically like a directory - it references a bunch of other trees // Tree is basically like a directory - it references a bunch of other trees
@@ -270,6 +272,28 @@ func (t *Tree) Decode(o plumbing.EncodedObject) (err error) {
return nil return nil
} }
type TreeEntrySorter []TreeEntry
func (s TreeEntrySorter) Len() int {
return len(s)
}
func (s TreeEntrySorter) Less(i, j int) bool {
name1 := s[i].Name
name2 := s[j].Name
if s[i].Mode == filemode.Dir {
name1 += "/"
}
if s[j].Mode == filemode.Dir {
name2 += "/"
}
return name1 < name2
}
func (s TreeEntrySorter) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
// Encode transforms a Tree into a plumbing.EncodedObject. // Encode transforms a Tree into a plumbing.EncodedObject.
func (t *Tree) Encode(o plumbing.EncodedObject) (err error) { func (t *Tree) Encode(o plumbing.EncodedObject) (err error) {
o.SetType(plumbing.TreeObject) o.SetType(plumbing.TreeObject)
@@ -279,7 +303,15 @@ func (t *Tree) Encode(o plumbing.EncodedObject) (err error) {
} }
defer ioutil.CheckClose(w, &err) defer ioutil.CheckClose(w, &err)
if !sort.IsSorted(TreeEntrySorter(t.Entries)) {
return ErrEntriesNotSorted
}
for _, entry := range t.Entries { for _, entry := range t.Entries {
if strings.IndexByte(entry.Name, 0) != -1 {
return fmt.Errorf("malformed filename %q", entry.Name)
}
if _, err = fmt.Fprintf(w, "%o %s", entry.Mode, entry.Name); err != nil { if _, err = fmt.Fprintf(w, "%o %s", entry.Mode, entry.Name); err != nil {
return err return err
} }
+3 -1
View File
@@ -88,7 +88,9 @@ func (t *treeNoder) Children() ([]noder.Noder, error) {
} }
} }
return transformChildren(parent) var err error
t.children, err = transformChildren(parent)
return t.children, err
} }
// Returns the children of a tree as treenoders. // Returns the children of a tree as treenoders.
+10 -10
View File
@@ -91,9 +91,9 @@ func advertisedReferences(ctx context.Context, s *session, serviceName string) (
} }
type client struct { type client struct {
c *http.Client client *http.Client
transports *lru.Cache transports *lru.Cache
m sync.RWMutex mutex sync.RWMutex
} }
// ClientOptions holds user configurable options for the client. // ClientOptions holds user configurable options for the client.
@@ -147,7 +147,7 @@ func NewClientWithOptions(c *http.Client, opts *ClientOptions) transport.Transpo
} }
} }
cl := &client{ cl := &client{
c: c, client: c,
} }
if opts != nil { if opts != nil {
@@ -234,10 +234,10 @@ func newSession(c *client, ep *transport.Endpoint, auth transport.AuthMethod) (*
// if the client wasn't configured to have a cache for transports then just configure // if the client wasn't configured to have a cache for transports then just configure
// the transport and use it directly, otherwise try to use the cache. // the transport and use it directly, otherwise try to use the cache.
if c.transports == nil { if c.transports == nil {
tr, ok := c.c.Transport.(*http.Transport) tr, ok := c.client.Transport.(*http.Transport)
if !ok { if !ok {
return nil, fmt.Errorf("expected underlying client transport to be of type: %s; got: %s", return nil, fmt.Errorf("expected underlying client transport to be of type: %s; got: %s",
reflect.TypeOf(transport), reflect.TypeOf(c.c.Transport)) reflect.TypeOf(transport), reflect.TypeOf(c.client.Transport))
} }
transport = tr.Clone() transport = tr.Clone()
@@ -258,7 +258,7 @@ func newSession(c *client, ep *transport.Endpoint, auth transport.AuthMethod) (*
transport, found = c.fetchTransport(transportOpts) transport, found = c.fetchTransport(transportOpts)
if !found { if !found {
transport = c.c.Transport.(*http.Transport).Clone() transport = c.client.Transport.(*http.Transport).Clone()
configureTransport(transport, ep) configureTransport(transport, ep)
c.addTransport(transportOpts, transport) c.addTransport(transportOpts, transport)
} }
@@ -266,12 +266,12 @@ func newSession(c *client, ep *transport.Endpoint, auth transport.AuthMethod) (*
httpClient = &http.Client{ httpClient = &http.Client{
Transport: transport, Transport: transport,
CheckRedirect: c.c.CheckRedirect, CheckRedirect: c.client.CheckRedirect,
Jar: c.c.Jar, Jar: c.client.Jar,
Timeout: c.c.Timeout, Timeout: c.client.Timeout,
} }
} else { } else {
httpClient = c.c httpClient = c.client
} }
s := &session{ s := &session{
+6 -6
View File
@@ -14,21 +14,21 @@ type transportOptions struct {
} }
func (c *client) addTransport(opts transportOptions, transport *http.Transport) { func (c *client) addTransport(opts transportOptions, transport *http.Transport) {
c.m.Lock() c.mutex.Lock()
c.transports.Add(opts, transport) c.transports.Add(opts, transport)
c.m.Unlock() c.mutex.Unlock()
} }
func (c *client) removeTransport(opts transportOptions) { func (c *client) removeTransport(opts transportOptions) {
c.m.Lock() c.mutex.Lock()
c.transports.Remove(opts) c.transports.Remove(opts)
c.m.Unlock() c.mutex.Unlock()
} }
func (c *client) fetchTransport(opts transportOptions) (*http.Transport, bool) { func (c *client) fetchTransport(opts transportOptions) (*http.Transport, bool) {
c.m.RLock() c.mutex.RLock()
t, ok := c.transports.Get(opts) t, ok := c.transports.Get(opts)
c.m.RUnlock() c.mutex.RUnlock()
if !ok { if !ok {
return nil, false return nil, false
} }
+3 -1
View File
@@ -49,7 +49,9 @@ type runner struct {
func (r *runner) Command(cmd string, ep *transport.Endpoint, auth transport.AuthMethod) (common.Command, error) { func (r *runner) Command(cmd string, ep *transport.Endpoint, auth transport.AuthMethod) (common.Command, error) {
c := &command{command: cmd, endpoint: ep, config: r.config} c := &command{command: cmd, endpoint: ep, config: r.config}
if auth != nil { if auth != nil {
c.setAuth(auth) if err := c.setAuth(auth); err != nil {
return nil, err
}
} }
if err := c.connect(); err != nil { if err := c.connect(); err != nil {
+31 -2
View File
@@ -470,6 +470,14 @@ func (r *Remote) fetch(ctx context.Context, o *FetchOptions) (sto storer.Referen
} }
} }
var updatedPrune bool
if o.Prune {
updatedPrune, err = r.pruneRemotes(o.RefSpecs, localRefs, remoteRefs)
if err != nil {
return nil, err
}
}
updated, err := r.updateLocalReferenceStorage(o.RefSpecs, refs, remoteRefs, specToRefs, o.Tags, o.Force) updated, err := r.updateLocalReferenceStorage(o.RefSpecs, refs, remoteRefs, specToRefs, o.Tags, o.Force)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -482,7 +490,7 @@ func (r *Remote) fetch(ctx context.Context, o *FetchOptions) (sto storer.Referen
} }
} }
if !updated { if !updated && !updatedPrune {
return remoteRefs, NoErrAlreadyUpToDate return remoteRefs, NoErrAlreadyUpToDate
} }
@@ -574,6 +582,27 @@ func (r *Remote) fetchPack(ctx context.Context, o *FetchOptions, s transport.Upl
return err return err
} }
func (r *Remote) pruneRemotes(specs []config.RefSpec, localRefs []*plumbing.Reference, remoteRefs memory.ReferenceStorage) (bool, error) {
var updatedPrune bool
for _, spec := range specs {
rev := spec.Reverse()
for _, ref := range localRefs {
if !rev.Match(ref.Name()) {
continue
}
_, err := remoteRefs.Reference(rev.Dst(ref.Name()))
if errors.Is(err, plumbing.ErrReferenceNotFound) {
updatedPrune = true
err := r.s.RemoveReference(ref.Name())
if err != nil {
return false, err
}
}
}
}
return updatedPrune, nil
}
func (r *Remote) addReferencesToUpdate( func (r *Remote) addReferencesToUpdate(
refspecs []config.RefSpec, refspecs []config.RefSpec,
localRefs []*plumbing.Reference, localRefs []*plumbing.Reference,
@@ -1099,7 +1128,7 @@ func isFastForward(s storer.EncodedObjectStorer, old, new plumbing.Hash, earlies
} }
found := false found := false
// stop iterating at the earlist shallow commit, ignoring its parents // stop iterating at the earliest shallow commit, ignoring its parents
// note: when pull depth is smaller than the number of new changes on the remote, this fails due to missing parents. // note: when pull depth is smaller than the number of new changes on the remote, this fails due to missing parents.
// as far as i can tell, without the commits in-between the shallow pull and the earliest shallow, there's no // as far as i can tell, without the commits in-between the shallow pull and the earliest shallow, there's no
// real way of telling whether it will be a fast-forward merge. // real way of telling whether it will be a fast-forward merge.
+38 -1
View File
@@ -64,6 +64,8 @@ var (
ErrPackedObjectsNotSupported = errors.New("packed objects not supported") ErrPackedObjectsNotSupported = errors.New("packed objects not supported")
ErrSHA256NotSupported = errors.New("go-git was not compiled with SHA256 support") ErrSHA256NotSupported = errors.New("go-git was not compiled with SHA256 support")
ErrAlternatePathNotSupported = errors.New("alternate path must use the file scheme") ErrAlternatePathNotSupported = errors.New("alternate path must use the file scheme")
ErrUnsupportedMergeStrategy = errors.New("unsupported merge strategy")
ErrFastForwardMergeNotPossible = errors.New("not possible to fast-forward merge changes")
) )
// Repository represents a git repository // Repository represents a git repository
@@ -1769,8 +1771,43 @@ func (r *Repository) RepackObjects(cfg *RepackConfig) (err error) {
return nil return nil
} }
// Merge merges the reference branch into the current branch.
//
// If the merge is not possible (or supported) returns an error without changing
// the HEAD for the current branch. Possible errors include:
// - The merge strategy is not supported.
// - The specific strategy cannot be used (e.g. using FastForwardMerge when one is not possible).
func (r *Repository) Merge(ref plumbing.Reference, opts MergeOptions) error {
if opts.Strategy != FastForwardMerge {
return ErrUnsupportedMergeStrategy
}
// Ignore error as not having a shallow list is optional here.
shallowList, _ := r.Storer.Shallow()
var earliestShallow *plumbing.Hash
if len(shallowList) > 0 {
earliestShallow = &shallowList[0]
}
head, err := r.Head()
if err != nil {
return err
}
ff, err := isFastForward(r.Storer, head.Hash(), ref.Hash(), earliestShallow)
if err != nil {
return err
}
if !ff {
return ErrFastForwardMergeNotPossible
}
return r.Storer.SetReference(plumbing.NewHashReference(head.Name(), ref.Hash()))
}
// createNewObjectPack is a helper for RepackObjects taking care // createNewObjectPack is a helper for RepackObjects taking care
// of creating a new pack. It is used so the the PackfileWriter // of creating a new pack. It is used so the PackfileWriter
// deferred close has the right scope. // deferred close has the right scope.
func (r *Repository) createNewObjectPack(cfg *RepackConfig) (h plumbing.Hash, err error) { func (r *Repository) createNewObjectPack(cfg *RepackConfig) (h plumbing.Hash, err error) {
ow := newObjectWalker(r.Storer) ow := newObjectWalker(r.Storer)
+33
View File
@@ -0,0 +1,33 @@
package git
import (
"io"
"github.com/go-git/go-git/v5/plumbing"
)
// signableObject is an object which can be signed.
type signableObject interface {
EncodeWithoutSignature(o plumbing.EncodedObject) error
}
// Signer is an interface for signing git objects.
// message is a reader containing the encoded object to be signed.
// Implementors should return the encoded signature and an error if any.
// See https://git-scm.com/docs/gitformat-signature for more information.
type Signer interface {
Sign(message io.Reader) ([]byte, error)
}
func signObject(signer Signer, obj signableObject) ([]byte, error) {
encoded := &plumbing.MemoryObject{}
if err := obj.EncodeWithoutSignature(encoded); err != nil {
return nil, err
}
r, err := encoded.Reader()
if err != nil {
return nil, err
}
return signer.Sign(r)
}
+41 -39
View File
@@ -29,6 +29,8 @@ type node struct {
hash []byte hash []byte
children []noder.Noder children []noder.Noder
isDir bool isDir bool
mode os.FileMode
size int64
} }
// NewRootNode returns the root node based on a given billy.Filesystem. // NewRootNode returns the root node based on a given billy.Filesystem.
@@ -48,8 +50,15 @@ func NewRootNode(
// difftree algorithm will detect changes in the contents of files and also in // difftree algorithm will detect changes in the contents of files and also in
// their mode. // their mode.
// //
// Please note that the hash is calculated on first invocation of Hash(),
// meaning that it will not update when the underlying file changes
// between invocations.
//
// The hash of a directory is always a 24-bytes slice of zero values // The hash of a directory is always a 24-bytes slice of zero values
func (n *node) Hash() []byte { func (n *node) Hash() []byte {
if n.hash == nil {
n.calculateHash()
}
return n.hash return n.hash
} }
@@ -121,81 +130,74 @@ func (n *node) calculateChildren() error {
func (n *node) newChildNode(file os.FileInfo) (*node, error) { func (n *node) newChildNode(file os.FileInfo) (*node, error) {
path := path.Join(n.path, file.Name()) path := path.Join(n.path, file.Name())
hash, err := n.calculateHash(path, file)
if err != nil {
return nil, err
}
node := &node{ node := &node{
fs: n.fs, fs: n.fs,
submodules: n.submodules, submodules: n.submodules,
path: path, path: path,
hash: hash,
isDir: file.IsDir(), isDir: file.IsDir(),
size: file.Size(),
mode: file.Mode(),
} }
if hash, isSubmodule := n.submodules[path]; isSubmodule { if _, isSubmodule := n.submodules[path]; isSubmodule {
node.hash = append(hash[:], filemode.Submodule.Bytes()...)
node.isDir = false node.isDir = false
} }
return node, nil return node, nil
} }
func (n *node) calculateHash(path string, file os.FileInfo) ([]byte, error) { func (n *node) calculateHash() {
if file.IsDir() { if n.isDir {
return make([]byte, 24), nil n.hash = make([]byte, 24)
return
}
mode, err := filemode.NewFromOSFileMode(n.mode)
if err != nil {
n.hash = plumbing.ZeroHash[:]
return
}
if submoduleHash, isSubmodule := n.submodules[n.path]; isSubmodule {
n.hash = append(submoduleHash[:], filemode.Submodule.Bytes()...)
return
} }
var hash plumbing.Hash var hash plumbing.Hash
var err error if n.mode&os.ModeSymlink != 0 {
if file.Mode()&os.ModeSymlink != 0 { hash = n.doCalculateHashForSymlink()
hash, err = n.doCalculateHashForSymlink(path, file)
} else { } else {
hash, err = n.doCalculateHashForRegular(path, file) hash = n.doCalculateHashForRegular()
} }
n.hash = append(hash[:], mode.Bytes()...)
if err != nil {
return nil, err
}
mode, err := filemode.NewFromOSFileMode(file.Mode())
if err != nil {
return nil, err
}
return append(hash[:], mode.Bytes()...), nil
} }
func (n *node) doCalculateHashForRegular(path string, file os.FileInfo) (plumbing.Hash, error) { func (n *node) doCalculateHashForRegular() plumbing.Hash {
f, err := n.fs.Open(path) f, err := n.fs.Open(n.path)
if err != nil { if err != nil {
return plumbing.ZeroHash, err return plumbing.ZeroHash
} }
defer f.Close() defer f.Close()
h := plumbing.NewHasher(plumbing.BlobObject, file.Size()) h := plumbing.NewHasher(plumbing.BlobObject, n.size)
if _, err := io.Copy(h, f); err != nil { if _, err := io.Copy(h, f); err != nil {
return plumbing.ZeroHash, err return plumbing.ZeroHash
} }
return h.Sum(), nil return h.Sum()
} }
func (n *node) doCalculateHashForSymlink(path string, file os.FileInfo) (plumbing.Hash, error) { func (n *node) doCalculateHashForSymlink() plumbing.Hash {
target, err := n.fs.Readlink(path) target, err := n.fs.Readlink(n.path)
if err != nil { if err != nil {
return plumbing.ZeroHash, err return plumbing.ZeroHash
} }
h := plumbing.NewHasher(plumbing.BlobObject, file.Size()) h := plumbing.NewHasher(plumbing.BlobObject, n.size)
if _, err := h.Write([]byte(target)); err != nil { if _, err := h.Write([]byte(target)); err != nil {
return plumbing.ZeroHash, err return plumbing.ZeroHash
} }
return h.Sum(), nil return h.Sum()
} }
func (n *node) String() string { func (n *node) String() string {
+10 -9
View File
@@ -227,20 +227,17 @@ func (w *Worktree) createBranch(opts *CheckoutOptions) error {
} }
func (w *Worktree) getCommitFromCheckoutOptions(opts *CheckoutOptions) (plumbing.Hash, error) { func (w *Worktree) getCommitFromCheckoutOptions(opts *CheckoutOptions) (plumbing.Hash, error) {
if !opts.Hash.IsZero() { hash := opts.Hash
return opts.Hash, nil if hash.IsZero() {
}
b, err := w.r.Reference(opts.Branch, true) b, err := w.r.Reference(opts.Branch, true)
if err != nil { if err != nil {
return plumbing.ZeroHash, err return plumbing.ZeroHash, err
} }
if !b.Name().IsTag() { hash = b.Hash()
return b.Hash(), nil
} }
o, err := w.r.Object(plumbing.AnyObject, b.Hash()) o, err := w.r.Object(plumbing.AnyObject, hash)
if err != nil { if err != nil {
return plumbing.ZeroHash, err return plumbing.ZeroHash, err
} }
@@ -248,7 +245,7 @@ func (w *Worktree) getCommitFromCheckoutOptions(opts *CheckoutOptions) (plumbing
switch o := o.(type) { switch o := o.(type) {
case *object.Tag: case *object.Tag:
if o.TargetType != plumbing.CommitObject { if o.TargetType != plumbing.CommitObject {
return plumbing.ZeroHash, fmt.Errorf("unsupported tag object target %q", o.TargetType) return plumbing.ZeroHash, fmt.Errorf("%w: tag target %q", object.ErrUnsupportedObject, o.TargetType)
} }
return o.Target, nil return o.Target, nil
@@ -256,7 +253,7 @@ func (w *Worktree) getCommitFromCheckoutOptions(opts *CheckoutOptions) (plumbing
return o.Hash, nil return o.Hash, nil
} }
return plumbing.ZeroHash, fmt.Errorf("unsupported tag target %q", o.Type()) return plumbing.ZeroHash, fmt.Errorf("%w: %q", object.ErrUnsupportedObject, o.Type())
} }
func (w *Worktree) setHEADToCommit(commit plumbing.Hash) error { func (w *Worktree) setHEADToCommit(commit plumbing.Hash) error {
@@ -431,6 +428,10 @@ var worktreeDeny = map[string]struct{}{
func validPath(paths ...string) error { func validPath(paths ...string) error {
for _, p := range paths { for _, p := range paths {
parts := strings.FieldsFunc(p, func(r rune) bool { return (r == '\\' || r == '/') }) parts := strings.FieldsFunc(p, func(r rune) bool { return (r == '\\' || r == '/') })
if len(parts) == 0 {
return fmt.Errorf("invalid path: %q", p)
}
if _, denied := worktreeDeny[strings.ToLower(parts[0])]; denied { if _, denied := worktreeDeny[strings.ToLower(parts[0])]; denied {
return fmt.Errorf("invalid path prefix: %q", p) return fmt.Errorf("invalid path prefix: %q", p)
} }
+26 -21
View File
@@ -3,6 +3,7 @@ package git
import ( import (
"bytes" "bytes"
"errors" "errors"
"io"
"path" "path"
"sort" "sort"
"strings" "strings"
@@ -14,6 +15,7 @@ import (
"github.com/go-git/go-git/v5/storage" "github.com/go-git/go-git/v5/storage"
"github.com/ProtonMail/go-crypto/openpgp" "github.com/ProtonMail/go-crypto/openpgp"
"github.com/ProtonMail/go-crypto/openpgp/packet"
"github.com/go-git/go-billy/v5" "github.com/go-git/go-billy/v5"
) )
@@ -43,15 +45,17 @@ func (w *Worktree) Commit(msg string, opts *CommitOptions) (plumbing.Hash, error
if err != nil { if err != nil {
return plumbing.ZeroHash, err return plumbing.ZeroHash, err
} }
headCommit, err := w.r.CommitObject(head.Hash())
t, err := w.r.getTreeFromCommitHash(head.Hash())
if err != nil { if err != nil {
return plumbing.ZeroHash, err return plumbing.ZeroHash, err
} }
treeHash = t.Hash opts.Parents = nil
opts.Parents = []plumbing.Hash{head.Hash()} if len(headCommit.ParentHashes) != 0 {
} else { opts.Parents = []plumbing.Hash{headCommit.ParentHashes[0]}
}
}
idx, err := w.r.Storer.Index() idx, err := w.r.Storer.Index()
if err != nil { if err != nil {
return plumbing.ZeroHash, err return plumbing.ZeroHash, err
@@ -66,7 +70,6 @@ func (w *Worktree) Commit(msg string, opts *CommitOptions) (plumbing.Hash, error
if err != nil { if err != nil {
return plumbing.ZeroHash, err return plumbing.ZeroHash, err
} }
}
commit, err := w.buildCommitObject(msg, opts, treeHash) commit, err := w.buildCommitObject(msg, opts, treeHash)
if err != nil { if err != nil {
@@ -125,12 +128,17 @@ func (w *Worktree) buildCommitObject(msg string, opts *CommitOptions, tree plumb
ParentHashes: opts.Parents, ParentHashes: opts.Parents,
} }
if opts.SignKey != nil { // Convert SignKey into a Signer if set. Existing Signer should take priority.
sig, err := w.buildCommitSignature(commit, opts.SignKey) signer := opts.Signer
if signer == nil && opts.SignKey != nil {
signer = &gpgSigner{key: opts.SignKey}
}
if signer != nil {
sig, err := signObject(signer, commit)
if err != nil { if err != nil {
return plumbing.ZeroHash, err return plumbing.ZeroHash, err
} }
commit.PGPSignature = sig commit.PGPSignature = string(sig)
} }
obj := w.r.Storer.NewEncodedObject() obj := w.r.Storer.NewEncodedObject()
@@ -140,20 +148,17 @@ func (w *Worktree) buildCommitObject(msg string, opts *CommitOptions, tree plumb
return w.r.Storer.SetEncodedObject(obj) return w.r.Storer.SetEncodedObject(obj)
} }
func (w *Worktree) buildCommitSignature(commit *object.Commit, signKey *openpgp.Entity) (string, error) { type gpgSigner struct {
encoded := &plumbing.MemoryObject{} key *openpgp.Entity
if err := commit.Encode(encoded); err != nil { cfg *packet.Config
return "", err }
}
r, err := encoded.Reader() func (s *gpgSigner) Sign(message io.Reader) ([]byte, error) {
if err != nil {
return "", err
}
var b bytes.Buffer var b bytes.Buffer
if err := openpgp.ArmoredDetachSign(&b, signKey, r, nil); err != nil { if err := openpgp.ArmoredDetachSign(&b, s.key, message, s.cfg); err != nil {
return "", err return nil, err
} }
return b.String(), nil return b.Bytes(), nil
} }
// buildTreeHelper converts a given index.Index file into multiple git objects // buildTreeHelper converts a given index.Index file into multiple git objects
+17 -10
View File
@@ -271,7 +271,7 @@ func diffTreeIsEquals(a, b noder.Hasher) bool {
// no error is returned. When path is a file, the blob.Hash is returned. // no error is returned. When path is a file, the blob.Hash is returned.
func (w *Worktree) Add(path string) (plumbing.Hash, error) { func (w *Worktree) Add(path string) (plumbing.Hash, error) {
// TODO(mcuadros): deprecate in favor of AddWithOption in v6. // TODO(mcuadros): deprecate in favor of AddWithOption in v6.
return w.doAdd(path, make([]gitignore.Pattern, 0)) return w.doAdd(path, make([]gitignore.Pattern, 0), false)
} }
func (w *Worktree) doAddDirectory(idx *index.Index, s Status, directory string, ignorePattern []gitignore.Pattern) (added bool, err error) { func (w *Worktree) doAddDirectory(idx *index.Index, s Status, directory string, ignorePattern []gitignore.Pattern) (added bool, err error) {
@@ -321,7 +321,7 @@ func (w *Worktree) AddWithOptions(opts *AddOptions) error {
} }
if opts.All { if opts.All {
_, err := w.doAdd(".", w.Excludes) _, err := w.doAdd(".", w.Excludes, false)
return err return err
} }
@@ -329,16 +329,11 @@ func (w *Worktree) AddWithOptions(opts *AddOptions) error {
return w.AddGlob(opts.Glob) return w.AddGlob(opts.Glob)
} }
_, err := w.Add(opts.Path) _, err := w.doAdd(opts.Path, make([]gitignore.Pattern, 0), opts.SkipStatus)
return err return err
} }
func (w *Worktree) doAdd(path string, ignorePattern []gitignore.Pattern) (plumbing.Hash, error) { func (w *Worktree) doAdd(path string, ignorePattern []gitignore.Pattern, skipStatus bool) (plumbing.Hash, error) {
s, err := w.Status()
if err != nil {
return plumbing.ZeroHash, err
}
idx, err := w.r.Storer.Index() idx, err := w.r.Storer.Index()
if err != nil { if err != nil {
return plumbing.ZeroHash, err return plumbing.ZeroHash, err
@@ -348,6 +343,17 @@ func (w *Worktree) doAdd(path string, ignorePattern []gitignore.Pattern) (plumbi
var added bool var added bool
fi, err := w.Filesystem.Lstat(path) fi, err := w.Filesystem.Lstat(path)
// status is required for doAddDirectory
var s Status
var err2 error
if !skipStatus || fi == nil || fi.IsDir() {
s, err2 = w.Status()
if err2 != nil {
return plumbing.ZeroHash, err2
}
}
if err != nil || !fi.IsDir() { if err != nil || !fi.IsDir() {
added, h, err = w.doAddFile(idx, s, path, ignorePattern) added, h, err = w.doAddFile(idx, s, path, ignorePattern)
} else { } else {
@@ -421,8 +427,9 @@ func (w *Worktree) AddGlob(pattern string) error {
// doAddFile create a new blob from path and update the index, added is true if // doAddFile create a new blob from path and update the index, added is true if
// the file added is different from the index. // the file added is different from the index.
// if s status is nil will skip the status check and update the index anyway
func (w *Worktree) doAddFile(idx *index.Index, s Status, path string, ignorePattern []gitignore.Pattern) (added bool, h plumbing.Hash, err error) { func (w *Worktree) doAddFile(idx *index.Index, s Status, path string, ignorePattern []gitignore.Pattern) (added bool, h plumbing.Hash, err error) {
if s.File(path).Worktree == Unmodified { if s != nil && s.File(path).Worktree == Unmodified {
return false, h, nil return false, h, nil
} }
if len(ignorePattern) > 0 { if len(ignorePattern) > 0 {
+8 -13
View File
@@ -34,8 +34,6 @@ const (
DiffInsert Operation = 1 DiffInsert Operation = 1
// DiffEqual item represents an equal diff. // DiffEqual item represents an equal diff.
DiffEqual Operation = 0 DiffEqual Operation = 0
//IndexSeparator is used to seperate the array indexes in an index string
IndexSeparator = ","
) )
// Diff represents one diff operation // Diff represents one diff operation
@@ -406,14 +404,11 @@ func (dmp *DiffMatchPatch) DiffLinesToRunes(text1, text2 string) ([]rune, []rune
func (dmp *DiffMatchPatch) DiffCharsToLines(diffs []Diff, lineArray []string) []Diff { func (dmp *DiffMatchPatch) DiffCharsToLines(diffs []Diff, lineArray []string) []Diff {
hydrated := make([]Diff, 0, len(diffs)) hydrated := make([]Diff, 0, len(diffs))
for _, aDiff := range diffs { for _, aDiff := range diffs {
chars := strings.Split(aDiff.Text, IndexSeparator) runes := []rune(aDiff.Text)
text := make([]string, len(chars)) text := make([]string, len(runes))
for i, r := range chars { for i, r := range runes {
i1, err := strconv.Atoi(r) text[i] = lineArray[runeToInt(r)]
if err == nil {
text[i] = lineArray[i1]
}
} }
aDiff.Text = strings.Join(text, "") aDiff.Text = strings.Join(text, "")
@@ -1313,17 +1308,17 @@ func (dmp *DiffMatchPatch) diffLinesToStrings(text1, text2 string) (string, stri
// '\x00' is a valid character, but various debuggers don't like it. So we'll insert a junk entry to avoid generating a null character. // '\x00' is a valid character, but various debuggers don't like it. So we'll insert a junk entry to avoid generating a null character.
lineArray := []string{""} // e.g. lineArray[4] == 'Hello\n' lineArray := []string{""} // e.g. lineArray[4] == 'Hello\n'
lineHash := make(map[string]int)
//Each string has the index of lineArray which it points to //Each string has the index of lineArray which it points to
strIndexArray1 := dmp.diffLinesToStringsMunge(text1, &lineArray) strIndexArray1 := dmp.diffLinesToStringsMunge(text1, &lineArray, lineHash)
strIndexArray2 := dmp.diffLinesToStringsMunge(text2, &lineArray) strIndexArray2 := dmp.diffLinesToStringsMunge(text2, &lineArray, lineHash)
return intArrayToString(strIndexArray1), intArrayToString(strIndexArray2), lineArray return intArrayToString(strIndexArray1), intArrayToString(strIndexArray2), lineArray
} }
// diffLinesToStringsMunge splits a text into an array of strings, and reduces the texts to a []string. // diffLinesToStringsMunge splits a text into an array of strings, and reduces the texts to a []string.
func (dmp *DiffMatchPatch) diffLinesToStringsMunge(text string, lineArray *[]string) []uint32 { func (dmp *DiffMatchPatch) diffLinesToStringsMunge(text string, lineArray *[]string, lineHash map[string]int) []uint32 {
// Walk the text, pulling out a substring for each line. text.split('\n') would would temporarily double our memory footprint. Modifying text would create many large strings to garbage collect. // Walk the text, pulling out a substring for each line. text.split('\n') would would temporarily double our memory footprint. Modifying text would create many large strings to garbage collect.
lineHash := map[string]int{} // e.g. lineHash['Hello\n'] == 4
lineStart := 0 lineStart := 0
lineEnd := -1 lineEnd := -1
strs := []uint32{} strs := []uint32{}
+92 -8
View File
@@ -9,11 +9,16 @@
package diffmatchpatch package diffmatchpatch
import ( import (
"strconv" "fmt"
"strings" "strings"
"unicode/utf8" "unicode/utf8"
) )
const UNICODE_INVALID_RANGE_START = 0xD800
const UNICODE_INVALID_RANGE_END = 0xDFFF
const UNICODE_INVALID_RANGE_DELTA = UNICODE_INVALID_RANGE_END - UNICODE_INVALID_RANGE_START + 1
const UNICODE_RANGE_MAX = 0x10FFFF
// unescaper unescapes selected chars for compatibility with JavaScript's encodeURI. // unescaper unescapes selected chars for compatibility with JavaScript's encodeURI.
// In speed critical applications this could be dropped since the receiving application will certainly decode these fine. Note that this function is case-sensitive. Thus "%3F" would not be unescaped. But this is ok because it is only called with the output of HttpUtility.UrlEncode which returns lowercase hex. Example: "%3f" -> "?", "%24" -> "$", etc. // In speed critical applications this could be dropped since the receiving application will certainly decode these fine. Note that this function is case-sensitive. Thus "%3F" would not be unescaped. But this is ok because it is only called with the output of HttpUtility.UrlEncode which returns lowercase hex. Example: "%3f" -> "?", "%24" -> "$", etc.
var unescaper = strings.NewReplacer( var unescaper = strings.NewReplacer(
@@ -93,14 +98,93 @@ func intArrayToString(ns []uint32) string {
return "" return ""
} }
indexSeparator := IndexSeparator[0] b := []rune{}
// Appr. 3 chars per num plus the comma.
b := []byte{}
for _, n := range ns { for _, n := range ns {
b = strconv.AppendInt(b, int64(n), 10) b = append(b, intToRune(n))
b = append(b, indexSeparator)
} }
b = b[:len(b)-1]
return string(b) return string(b)
} }
// These constants define the number of bits representable
// in 1,2,3,4 byte utf8 sequences, respectively.
const ONE_BYTE_BITS = 7
const TWO_BYTE_BITS = 11
const THREE_BYTE_BITS = 16
const FOUR_BYTE_BITS = 21
// Helper for getting a sequence of bits from an integer.
func getBits(i uint32, cnt byte, from byte) byte {
return byte((i >> from) & ((1 << cnt) - 1))
}
// Converts an integer in the range 0~1112060 into a rune.
// Based on the ranges table in https://en.wikipedia.org/wiki/UTF-8
func intToRune(i uint32) rune {
if i < (1 << ONE_BYTE_BITS) {
return rune(i)
}
if i < (1 << TWO_BYTE_BITS) {
r, size := utf8.DecodeRune([]byte{0b11000000 | getBits(i, 5, 6), 0b10000000 | getBits(i, 6, 0)})
if size != 2 || r == utf8.RuneError {
panic(fmt.Sprintf("Error encoding an int %d with size 2, got rune %v and size %d", size, r, i))
}
return r
}
// Last -3 here needed because for some reason 3rd to last codepoint 65533 in this range
// was returning utf8.RuneError during encoding.
if i < ((1 << THREE_BYTE_BITS) - UNICODE_INVALID_RANGE_DELTA - 3) {
if i >= UNICODE_INVALID_RANGE_START {
i += UNICODE_INVALID_RANGE_DELTA
}
r, size := utf8.DecodeRune([]byte{0b11100000 | getBits(i, 4, 12), 0b10000000 | getBits(i, 6, 6), 0b10000000 | getBits(i, 6, 0)})
if size != 3 || r == utf8.RuneError {
panic(fmt.Sprintf("Error encoding an int %d with size 3, got rune %v and size %d", size, r, i))
}
return r
}
if i < (1<<FOUR_BYTE_BITS - UNICODE_INVALID_RANGE_DELTA - 3) {
i += UNICODE_INVALID_RANGE_DELTA + 3
r, size := utf8.DecodeRune([]byte{0b11110000 | getBits(i, 3, 18), 0b10000000 | getBits(i, 6, 12), 0b10000000 | getBits(i, 6, 6), 0b10000000 | getBits(i, 6, 0)})
if size != 4 || r == utf8.RuneError {
panic(fmt.Sprintf("Error encoding an int %d with size 4, got rune %v and size %d", size, r, i))
}
return r
}
panic(fmt.Sprintf("The integer %d is too large for runeToInt()", i))
}
// Converts a rune generated by intToRune back to an integer
func runeToInt(r rune) uint32 {
i := uint32(r)
if i < (1 << ONE_BYTE_BITS) {
return i
}
bytes := []byte{0, 0, 0, 0}
size := utf8.EncodeRune(bytes, r)
if size == 2 {
return uint32(bytes[0]&0b11111)<<6 | uint32(bytes[1]&0b111111)
}
if size == 3 {
result := uint32(bytes[0]&0b1111)<<12 | uint32(bytes[1]&0b111111)<<6 | uint32(bytes[2]&0b111111)
if result >= UNICODE_INVALID_RANGE_END {
return result - UNICODE_INVALID_RANGE_DELTA
}
return result
}
if size == 4 {
result := uint32(bytes[0]&0b111)<<18 | uint32(bytes[1]&0b111111)<<12 | uint32(bytes[2]&0b111111)<<6 | uint32(bytes[3]&0b111111)
return result - UNICODE_INVALID_RANGE_DELTA - 3
}
panic(fmt.Sprintf("Unexpected state decoding rune=%v size=%d", r, size))
}
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright 2023 Skeema LLC and the Skeema Knownhosts authors Copyright 2024 Skeema LLC and the Skeema Knownhosts authors
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
+1 -1
View File
@@ -100,7 +100,7 @@ config := &ssh.ClientConfig{
## License ## License
**Source code copyright 2023 Skeema LLC and the Skeema Knownhosts authors** **Source code copyright 2024 Skeema LLC and the Skeema Knownhosts authors**
```text ```text
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
+12 -2
View File
@@ -76,13 +76,23 @@ func (hkcb HostKeyCallback) HostKeyAlgorithms(hostWithPort string) (algos []stri
// example by https://github.com/golang/crypto/pull/254. // example by https://github.com/golang/crypto/pull/254.
hostKeys := hkcb.HostKeys(hostWithPort) hostKeys := hkcb.HostKeys(hostWithPort)
seen := make(map[string]struct{}, len(hostKeys)) seen := make(map[string]struct{}, len(hostKeys))
for _, key := range hostKeys { addAlgo := func(typ string) {
typ := key.Type()
if _, already := seen[typ]; !already { if _, already := seen[typ]; !already {
algos = append(algos, typ) algos = append(algos, typ)
seen[typ] = struct{}{} seen[typ] = struct{}{}
} }
} }
for _, key := range hostKeys {
typ := key.Type()
if typ == ssh.KeyAlgoRSA {
// KeyAlgoRSASHA256 and KeyAlgoRSASHA512 are only public key algorithms,
// not public key formats, so they can't appear as a PublicKey.Type.
// The corresponding PublicKey.Type is KeyAlgoRSA. See RFC 8332, Section 2.
addAlgo(ssh.KeyAlgoRSASHA512)
addAlgo(ssh.KeyAlgoRSASHA256)
}
addAlgo(typ)
}
return algos return algos
} }
+25 -3
View File
@@ -28,6 +28,8 @@ var (
uint32Type = reflect.TypeOf(uint32(1)) uint32Type = reflect.TypeOf(uint32(1))
uint64Type = reflect.TypeOf(uint64(1)) uint64Type = reflect.TypeOf(uint64(1))
uintptrType = reflect.TypeOf(uintptr(1))
float32Type = reflect.TypeOf(float32(1)) float32Type = reflect.TypeOf(float32(1))
float64Type = reflect.TypeOf(float64(1)) float64Type = reflect.TypeOf(float64(1))
@@ -308,11 +310,11 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
case reflect.Struct: case reflect.Struct:
{ {
// All structs enter here. We're not interested in most types. // All structs enter here. We're not interested in most types.
if !canConvert(obj1Value, timeType) { if !obj1Value.CanConvert(timeType) {
break break
} }
// time.Time can compared! // time.Time can be compared!
timeObj1, ok := obj1.(time.Time) timeObj1, ok := obj1.(time.Time)
if !ok { if !ok {
timeObj1 = obj1Value.Convert(timeType).Interface().(time.Time) timeObj1 = obj1Value.Convert(timeType).Interface().(time.Time)
@@ -328,7 +330,7 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
case reflect.Slice: case reflect.Slice:
{ {
// We only care about the []byte type. // We only care about the []byte type.
if !canConvert(obj1Value, bytesType) { if !obj1Value.CanConvert(bytesType) {
break break
} }
@@ -345,6 +347,26 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
return CompareType(bytes.Compare(bytesObj1, bytesObj2)), true return CompareType(bytes.Compare(bytesObj1, bytesObj2)), true
} }
case reflect.Uintptr:
{
uintptrObj1, ok := obj1.(uintptr)
if !ok {
uintptrObj1 = obj1Value.Convert(uintptrType).Interface().(uintptr)
}
uintptrObj2, ok := obj2.(uintptr)
if !ok {
uintptrObj2 = obj2Value.Convert(uintptrType).Interface().(uintptr)
}
if uintptrObj1 > uintptrObj2 {
return compareGreater, true
}
if uintptrObj1 == uintptrObj2 {
return compareEqual, true
}
if uintptrObj1 < uintptrObj2 {
return compareLess, true
}
}
} }
return compareEqual, false return compareEqual, false
@@ -1,16 +0,0 @@
//go:build go1.17
// +build go1.17
// TODO: once support for Go 1.16 is dropped, this file can be
// merged/removed with assertion_compare_go1.17_test.go and
// assertion_compare_legacy.go
package assert
import "reflect"
// Wrapper around reflect.Value.CanConvert, for compatibility
// reasons.
func canConvert(value reflect.Value, to reflect.Type) bool {
return value.CanConvert(to)
}
-16
View File
@@ -1,16 +0,0 @@
//go:build !go1.17
// +build !go1.17
// TODO: once support for Go 1.16 is dropped, this file can be
// merged/removed with assertion_compare_go1.17_test.go and
// assertion_compare_can_convert.go
package assert
import "reflect"
// Older versions of Go does not have the reflect.Value.CanConvert
// method.
func canConvert(value reflect.Value, to reflect.Type) bool {
return false
}
+21 -11
View File
@@ -1,7 +1,4 @@
/* // Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT.
* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen
* THIS FILE MUST NOT BE EDITED BY HAND
*/
package assert package assert
@@ -107,7 +104,7 @@ func EqualExportedValuesf(t TestingT, expected interface{}, actual interface{},
return EqualExportedValues(t, expected, actual, append([]interface{}{msg}, args...)...) return EqualExportedValues(t, expected, actual, append([]interface{}{msg}, args...)...)
} }
// EqualValuesf asserts that two objects are equal or convertable to the same types // EqualValuesf asserts that two objects are equal or convertible to the same types
// and equal. // and equal.
// //
// assert.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted") // assert.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted")
@@ -616,6 +613,16 @@ func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interf
return NotErrorIs(t, err, target, append([]interface{}{msg}, args...)...) return NotErrorIs(t, err, target, append([]interface{}{msg}, args...)...)
} }
// NotImplementsf asserts that an object does not implement the specified interface.
//
// assert.NotImplementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted")
func NotImplementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
return NotImplements(t, interfaceObject, object, append([]interface{}{msg}, args...)...)
}
// NotNilf asserts that the specified object is not nil. // NotNilf asserts that the specified object is not nil.
// //
// assert.NotNilf(t, err, "error message %s", "formatted") // assert.NotNilf(t, err, "error message %s", "formatted")
@@ -660,10 +667,12 @@ func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string,
return NotSame(t, expected, actual, append([]interface{}{msg}, args...)...) return NotSame(t, expected, actual, append([]interface{}{msg}, args...)...)
} }
// NotSubsetf asserts that the specified list(array, slice...) contains not all // NotSubsetf asserts that the specified list(array, slice...) or map does NOT
// elements given in the specified subset(array, slice...). // contain all elements given in the specified subset list(array, slice...) or
// map.
// //
// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") // assert.NotSubsetf(t, [1, 3, 4], [1, 2], "error message %s", "formatted")
// assert.NotSubsetf(t, {"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted")
func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok { if h, ok := t.(tHelper); ok {
h.Helper() h.Helper()
@@ -747,10 +756,11 @@ func Samef(t TestingT, expected interface{}, actual interface{}, msg string, arg
return Same(t, expected, actual, append([]interface{}{msg}, args...)...) return Same(t, expected, actual, append([]interface{}{msg}, args...)...)
} }
// Subsetf asserts that the specified list(array, slice...) contains all // Subsetf asserts that the specified list(array, slice...) or map contains all
// elements given in the specified subset(array, slice...). // elements given in the specified subset list(array, slice...) or map.
// //
// assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") // assert.Subsetf(t, [1, 2, 3], [1, 2], "error message %s", "formatted")
// assert.Subsetf(t, {"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted")
func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok { if h, ok := t.(tHelper); ok {
h.Helper() h.Helper()
+41 -18
View File
@@ -1,7 +1,4 @@
/* // Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT.
* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen
* THIS FILE MUST NOT BE EDITED BY HAND
*/
package assert package assert
@@ -189,7 +186,7 @@ func (a *Assertions) EqualExportedValuesf(expected interface{}, actual interface
return EqualExportedValuesf(a.t, expected, actual, msg, args...) return EqualExportedValuesf(a.t, expected, actual, msg, args...)
} }
// EqualValues asserts that two objects are equal or convertable to the same types // EqualValues asserts that two objects are equal or convertible to the same types
// and equal. // and equal.
// //
// a.EqualValues(uint32(123), int32(123)) // a.EqualValues(uint32(123), int32(123))
@@ -200,7 +197,7 @@ func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAn
return EqualValues(a.t, expected, actual, msgAndArgs...) return EqualValues(a.t, expected, actual, msgAndArgs...)
} }
// EqualValuesf asserts that two objects are equal or convertable to the same types // EqualValuesf asserts that two objects are equal or convertible to the same types
// and equal. // and equal.
// //
// a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted") // a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted")
@@ -1221,6 +1218,26 @@ func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...in
return NotErrorIsf(a.t, err, target, msg, args...) return NotErrorIsf(a.t, err, target, msg, args...)
} }
// NotImplements asserts that an object does not implement the specified interface.
//
// a.NotImplements((*MyInterface)(nil), new(MyObject))
func (a *Assertions) NotImplements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
return NotImplements(a.t, interfaceObject, object, msgAndArgs...)
}
// NotImplementsf asserts that an object does not implement the specified interface.
//
// a.NotImplementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted")
func (a *Assertions) NotImplementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
return NotImplementsf(a.t, interfaceObject, object, msg, args...)
}
// NotNil asserts that the specified object is not nil. // NotNil asserts that the specified object is not nil.
// //
// a.NotNil(err) // a.NotNil(err)
@@ -1309,10 +1326,12 @@ func (a *Assertions) NotSamef(expected interface{}, actual interface{}, msg stri
return NotSamef(a.t, expected, actual, msg, args...) return NotSamef(a.t, expected, actual, msg, args...)
} }
// NotSubset asserts that the specified list(array, slice...) contains not all // NotSubset asserts that the specified list(array, slice...) or map does NOT
// elements given in the specified subset(array, slice...). // contain all elements given in the specified subset list(array, slice...) or
// map.
// //
// a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") // a.NotSubset([1, 3, 4], [1, 2])
// a.NotSubset({"x": 1, "y": 2}, {"z": 3})
func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool {
if h, ok := a.t.(tHelper); ok { if h, ok := a.t.(tHelper); ok {
h.Helper() h.Helper()
@@ -1320,10 +1339,12 @@ func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs
return NotSubset(a.t, list, subset, msgAndArgs...) return NotSubset(a.t, list, subset, msgAndArgs...)
} }
// NotSubsetf asserts that the specified list(array, slice...) contains not all // NotSubsetf asserts that the specified list(array, slice...) or map does NOT
// elements given in the specified subset(array, slice...). // contain all elements given in the specified subset list(array, slice...) or
// map.
// //
// a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") // a.NotSubsetf([1, 3, 4], [1, 2], "error message %s", "formatted")
// a.NotSubsetf({"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted")
func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool {
if h, ok := a.t.(tHelper); ok { if h, ok := a.t.(tHelper); ok {
h.Helper() h.Helper()
@@ -1483,10 +1504,11 @@ func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string,
return Samef(a.t, expected, actual, msg, args...) return Samef(a.t, expected, actual, msg, args...)
} }
// Subset asserts that the specified list(array, slice...) contains all // Subset asserts that the specified list(array, slice...) or map contains all
// elements given in the specified subset(array, slice...). // elements given in the specified subset list(array, slice...) or map.
// //
// a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") // a.Subset([1, 2, 3], [1, 2])
// a.Subset({"x": 1, "y": 2}, {"x": 1})
func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool {
if h, ok := a.t.(tHelper); ok { if h, ok := a.t.(tHelper); ok {
h.Helper() h.Helper()
@@ -1494,10 +1516,11 @@ func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...
return Subset(a.t, list, subset, msgAndArgs...) return Subset(a.t, list, subset, msgAndArgs...)
} }
// Subsetf asserts that the specified list(array, slice...) contains all // Subsetf asserts that the specified list(array, slice...) or map contains all
// elements given in the specified subset(array, slice...). // elements given in the specified subset list(array, slice...) or map.
// //
// a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") // a.Subsetf([1, 2, 3], [1, 2], "error message %s", "formatted")
// a.Subsetf({"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted")
func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool {
if h, ok := a.t.(tHelper); ok { if h, ok := a.t.(tHelper); ok {
h.Helper() h.Helper()
+128 -77
View File
@@ -19,7 +19,7 @@ import (
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
"github.com/pmezard/go-difflib/difflib" "github.com/pmezard/go-difflib/difflib"
yaml "gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
) )
//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_format.go.tmpl" //go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_format.go.tmpl"
@@ -110,7 +110,12 @@ func copyExportedFields(expected interface{}) interface{} {
return result.Interface() return result.Interface()
case reflect.Array, reflect.Slice: case reflect.Array, reflect.Slice:
result := reflect.MakeSlice(expectedType, expectedValue.Len(), expectedValue.Len()) var result reflect.Value
if expectedKind == reflect.Array {
result = reflect.New(reflect.ArrayOf(expectedValue.Len(), expectedType.Elem())).Elem()
} else {
result = reflect.MakeSlice(expectedType, expectedValue.Len(), expectedValue.Len())
}
for i := 0; i < expectedValue.Len(); i++ { for i := 0; i < expectedValue.Len(); i++ {
index := expectedValue.Index(i) index := expectedValue.Index(i)
if isNil(index) { if isNil(index) {
@@ -140,6 +145,8 @@ func copyExportedFields(expected interface{}) interface{} {
// structures. // structures.
// //
// This function does no assertion of any kind. // This function does no assertion of any kind.
//
// Deprecated: Use [EqualExportedValues] instead.
func ObjectsExportedFieldsAreEqual(expected, actual interface{}) bool { func ObjectsExportedFieldsAreEqual(expected, actual interface{}) bool {
expectedCleaned := copyExportedFields(expected) expectedCleaned := copyExportedFields(expected)
actualCleaned := copyExportedFields(actual) actualCleaned := copyExportedFields(actual)
@@ -153,17 +160,40 @@ func ObjectsAreEqualValues(expected, actual interface{}) bool {
return true return true
} }
actualType := reflect.TypeOf(actual)
if actualType == nil {
return false
}
expectedValue := reflect.ValueOf(expected) expectedValue := reflect.ValueOf(expected)
if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) { actualValue := reflect.ValueOf(actual)
// Attempt comparison after type conversion if !expectedValue.IsValid() || !actualValue.IsValid() {
return reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), actual) return false
} }
expectedType := expectedValue.Type()
actualType := actualValue.Type()
if !expectedType.ConvertibleTo(actualType) {
return false return false
}
if !isNumericType(expectedType) || !isNumericType(actualType) {
// Attempt comparison after type conversion
return reflect.DeepEqual(
expectedValue.Convert(actualType).Interface(), actual,
)
}
// If BOTH values are numeric, there are chances of false positives due
// to overflow or underflow. So, we need to make sure to always convert
// the smaller type to a larger type before comparing.
if expectedType.Size() >= actualType.Size() {
return actualValue.Convert(expectedType).Interface() == expected
}
return expectedValue.Convert(actualType).Interface() == actual
}
// isNumericType returns true if the type is one of:
// int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64,
// float32, float64, complex64, complex128
func isNumericType(t reflect.Type) bool {
return t.Kind() >= reflect.Int && t.Kind() <= reflect.Complex128
} }
/* CallerInfo is necessary because the assert functions use the testing object /* CallerInfo is necessary because the assert functions use the testing object
@@ -266,7 +296,7 @@ func messageFromMsgAndArgs(msgAndArgs ...interface{}) string {
// Aligns the provided message so that all lines after the first line start at the same location as the first line. // Aligns the provided message so that all lines after the first line start at the same location as the first line.
// Assumes that the first line starts at the correct location (after carriage return, tab, label, spacer and tab). // Assumes that the first line starts at the correct location (after carriage return, tab, label, spacer and tab).
// The longestLabelLen parameter specifies the length of the longest label in the output (required becaues this is the // The longestLabelLen parameter specifies the length of the longest label in the output (required because this is the
// basis on which the alignment occurs). // basis on which the alignment occurs).
func indentMessageLines(message string, longestLabelLen int) string { func indentMessageLines(message string, longestLabelLen int) string {
outBuf := new(bytes.Buffer) outBuf := new(bytes.Buffer)
@@ -382,6 +412,25 @@ func Implements(t TestingT, interfaceObject interface{}, object interface{}, msg
return true return true
} }
// NotImplements asserts that an object does not implement the specified interface.
//
// assert.NotImplements(t, (*MyInterface)(nil), new(MyObject))
func NotImplements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
interfaceType := reflect.TypeOf(interfaceObject).Elem()
if object == nil {
return Fail(t, fmt.Sprintf("Cannot check if nil does not implement %v", interfaceType), msgAndArgs...)
}
if reflect.TypeOf(object).Implements(interfaceType) {
return Fail(t, fmt.Sprintf("%T implements %v", object, interfaceType), msgAndArgs...)
}
return true
}
// IsType asserts that the specified objects are of the same type. // IsType asserts that the specified objects are of the same type.
func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok { if h, ok := t.(tHelper); ok {
@@ -496,7 +545,7 @@ func samePointers(first, second interface{}) bool {
// representations appropriate to be presented to the user. // representations appropriate to be presented to the user.
// //
// If the values are not of like type, the returned strings will be prefixed // If the values are not of like type, the returned strings will be prefixed
// with the type name, and the value will be enclosed in parenthesis similar // with the type name, and the value will be enclosed in parentheses similar
// to a type conversion in the Go grammar. // to a type conversion in the Go grammar.
func formatUnequalValues(expected, actual interface{}) (e string, a string) { func formatUnequalValues(expected, actual interface{}) (e string, a string) {
if reflect.TypeOf(expected) != reflect.TypeOf(actual) { if reflect.TypeOf(expected) != reflect.TypeOf(actual) {
@@ -523,7 +572,7 @@ func truncatingFormat(data interface{}) string {
return value return value
} }
// EqualValues asserts that two objects are equal or convertable to the same types // EqualValues asserts that two objects are equal or convertible to the same types
// and equal. // and equal.
// //
// assert.EqualValues(t, uint32(123), int32(123)) // assert.EqualValues(t, uint32(123), int32(123))
@@ -566,12 +615,19 @@ func EqualExportedValues(t TestingT, expected, actual interface{}, msgAndArgs ..
return Fail(t, fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...) return Fail(t, fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...)
} }
if aType.Kind() == reflect.Ptr {
aType = aType.Elem()
}
if bType.Kind() == reflect.Ptr {
bType = bType.Elem()
}
if aType.Kind() != reflect.Struct { if aType.Kind() != reflect.Struct {
return Fail(t, fmt.Sprintf("Types expected to both be struct \n\t%v != %v", aType.Kind(), reflect.Struct), msgAndArgs...) return Fail(t, fmt.Sprintf("Types expected to both be struct or pointer to struct \n\t%v != %v", aType.Kind(), reflect.Struct), msgAndArgs...)
} }
if bType.Kind() != reflect.Struct { if bType.Kind() != reflect.Struct {
return Fail(t, fmt.Sprintf("Types expected to both be struct \n\t%v != %v", bType.Kind(), reflect.Struct), msgAndArgs...) return Fail(t, fmt.Sprintf("Types expected to both be struct or pointer to struct \n\t%v != %v", bType.Kind(), reflect.Struct), msgAndArgs...)
} }
expected = copyExportedFields(expected) expected = copyExportedFields(expected)
@@ -620,17 +676,6 @@ func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
return Fail(t, "Expected value not to be nil.", msgAndArgs...) return Fail(t, "Expected value not to be nil.", msgAndArgs...)
} }
// containsKind checks if a specified kind in the slice of kinds.
func containsKind(kinds []reflect.Kind, kind reflect.Kind) bool {
for i := 0; i < len(kinds); i++ {
if kind == kinds[i] {
return true
}
}
return false
}
// isNil checks if a specified object is nil or not, without Failing. // isNil checks if a specified object is nil or not, without Failing.
func isNil(object interface{}) bool { func isNil(object interface{}) bool {
if object == nil { if object == nil {
@@ -638,16 +683,13 @@ func isNil(object interface{}) bool {
} }
value := reflect.ValueOf(object) value := reflect.ValueOf(object)
kind := value.Kind() switch value.Kind() {
isNilableKind := containsKind( case
[]reflect.Kind{
reflect.Chan, reflect.Func, reflect.Chan, reflect.Func,
reflect.Interface, reflect.Map, reflect.Interface, reflect.Map,
reflect.Ptr, reflect.Slice, reflect.UnsafePointer}, reflect.Ptr, reflect.Slice, reflect.UnsafePointer:
kind)
if isNilableKind && value.IsNil() { return value.IsNil()
return true
} }
return false return false
@@ -731,16 +773,14 @@ func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
} }
// getLen try to get length of object. // getLen tries to get the length of an object.
// return (false, 0) if impossible. // It returns (0, false) if impossible.
func getLen(x interface{}) (ok bool, length int) { func getLen(x interface{}) (length int, ok bool) {
v := reflect.ValueOf(x) v := reflect.ValueOf(x)
defer func() { defer func() {
if e := recover(); e != nil { ok = recover() == nil
ok = false
}
}() }()
return true, v.Len() return v.Len(), true
} }
// Len asserts that the specified object has specific length. // Len asserts that the specified object has specific length.
@@ -751,13 +791,13 @@ func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{})
if h, ok := t.(tHelper); ok { if h, ok := t.(tHelper); ok {
h.Helper() h.Helper()
} }
ok, l := getLen(object) l, ok := getLen(object)
if !ok { if !ok {
return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", object), msgAndArgs...) return Fail(t, fmt.Sprintf("\"%v\" could not be applied builtin len()", object), msgAndArgs...)
} }
if l != length { if l != length {
return Fail(t, fmt.Sprintf("\"%s\" should have %d item(s), but has %d", object, length, l), msgAndArgs...) return Fail(t, fmt.Sprintf("\"%v\" should have %d item(s), but has %d", object, length, l), msgAndArgs...)
} }
return true return true
} }
@@ -919,10 +959,11 @@ func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{})
} }
// Subset asserts that the specified list(array, slice...) contains all // Subset asserts that the specified list(array, slice...) or map contains all
// elements given in the specified subset(array, slice...). // elements given in the specified subset list(array, slice...) or map.
// //
// assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") // assert.Subset(t, [1, 2, 3], [1, 2])
// assert.Subset(t, {"x": 1, "y": 2}, {"x": 1})
func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) {
if h, ok := t.(tHelper); ok { if h, ok := t.(tHelper); ok {
h.Helper() h.Helper()
@@ -975,10 +1016,12 @@ func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok
return true return true
} }
// NotSubset asserts that the specified list(array, slice...) contains not all // NotSubset asserts that the specified list(array, slice...) or map does NOT
// elements given in the specified subset(array, slice...). // contain all elements given in the specified subset list(array, slice...) or
// map.
// //
// assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") // assert.NotSubset(t, [1, 3, 4], [1, 2])
// assert.NotSubset(t, {"x": 1, "y": 2}, {"z": 3})
func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) {
if h, ok := t.(tHelper); ok { if h, ok := t.(tHelper); ok {
h.Helper() h.Helper()
@@ -1439,7 +1482,7 @@ func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAnd
h.Helper() h.Helper()
} }
if math.IsNaN(epsilon) { if math.IsNaN(epsilon) {
return Fail(t, "epsilon must not be NaN") return Fail(t, "epsilon must not be NaN", msgAndArgs...)
} }
actualEpsilon, err := calcRelativeError(expected, actual) actualEpsilon, err := calcRelativeError(expected, actual)
if err != nil { if err != nil {
@@ -1458,19 +1501,26 @@ func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, m
if h, ok := t.(tHelper); ok { if h, ok := t.(tHelper); ok {
h.Helper() h.Helper()
} }
if expected == nil || actual == nil ||
reflect.TypeOf(actual).Kind() != reflect.Slice || if expected == nil || actual == nil {
reflect.TypeOf(expected).Kind() != reflect.Slice {
return Fail(t, "Parameters must be slice", msgAndArgs...) return Fail(t, "Parameters must be slice", msgAndArgs...)
} }
actualSlice := reflect.ValueOf(actual)
expectedSlice := reflect.ValueOf(expected) expectedSlice := reflect.ValueOf(expected)
actualSlice := reflect.ValueOf(actual)
for i := 0; i < actualSlice.Len(); i++ { if expectedSlice.Type().Kind() != reflect.Slice {
result := InEpsilon(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), epsilon) return Fail(t, "Expected value must be slice", msgAndArgs...)
if !result { }
return result
expectedLen := expectedSlice.Len()
if !IsType(t, expected, actual) || !Len(t, actual, expectedLen) {
return false
}
for i := 0; i < expectedLen; i++ {
if !InEpsilon(t, expectedSlice.Index(i).Interface(), actualSlice.Index(i).Interface(), epsilon, "at index %d", i) {
return false
} }
} }
@@ -1870,23 +1920,18 @@ func (c *CollectT) Errorf(format string, args ...interface{}) {
} }
// FailNow panics. // FailNow panics.
func (c *CollectT) FailNow() { func (*CollectT) FailNow() {
panic("Assertion failed") panic("Assertion failed")
} }
// Reset clears the collected errors. // Deprecated: That was a method for internal usage that should not have been published. Now just panics.
func (c *CollectT) Reset() { func (*CollectT) Reset() {
c.errors = nil panic("Reset() is deprecated")
} }
// Copy copies the collected errors to the supplied t. // Deprecated: That was a method for internal usage that should not have been published. Now just panics.
func (c *CollectT) Copy(t TestingT) { func (*CollectT) Copy(TestingT) {
if tt, ok := t.(tHelper); ok { panic("Copy() is deprecated")
tt.Helper()
}
for _, err := range c.errors {
t.Errorf("%v", err)
}
} }
// EventuallyWithT asserts that given condition will be met in waitFor time, // EventuallyWithT asserts that given condition will be met in waitFor time,
@@ -1912,8 +1957,8 @@ func EventuallyWithT(t TestingT, condition func(collect *CollectT), waitFor time
h.Helper() h.Helper()
} }
collect := new(CollectT) var lastFinishedTickErrs []error
ch := make(chan bool, 1) ch := make(chan []error, 1)
timer := time.NewTimer(waitFor) timer := time.NewTimer(waitFor)
defer timer.Stop() defer timer.Stop()
@@ -1924,19 +1969,25 @@ func EventuallyWithT(t TestingT, condition func(collect *CollectT), waitFor time
for tick := ticker.C; ; { for tick := ticker.C; ; {
select { select {
case <-timer.C: case <-timer.C:
collect.Copy(t) for _, err := range lastFinishedTickErrs {
t.Errorf("%v", err)
}
return Fail(t, "Condition never satisfied", msgAndArgs...) return Fail(t, "Condition never satisfied", msgAndArgs...)
case <-tick: case <-tick:
tick = nil tick = nil
collect.Reset()
go func() { go func() {
condition(collect) collect := new(CollectT)
ch <- len(collect.errors) == 0 defer func() {
ch <- collect.errors
}() }()
case v := <-ch: condition(collect)
if v { }()
case errs := <-ch:
if len(errs) == 0 {
return true return true
} }
// Keep the errors from the last ended condition, so that they can be copied to t if timeout is reached.
lastFinishedTickErrs = errs
tick = ticker.C tick = ticker.C
} }
} }
+15 -12
View File
@@ -12,7 +12,7 @@ import (
// an error if building a new request fails. // an error if building a new request fails.
func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) { func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) {
w := httptest.NewRecorder() w := httptest.NewRecorder()
req, err := http.NewRequest(method, url, nil) req, err := http.NewRequest(method, url, http.NoBody)
if err != nil { if err != nil {
return -1, err return -1, err
} }
@@ -32,12 +32,12 @@ func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, value
} }
code, err := httpCode(handler, method, url, values) code, err := httpCode(handler, method, url, values)
if err != nil { if err != nil {
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...)
} }
isSuccessCode := code >= http.StatusOK && code <= http.StatusPartialContent isSuccessCode := code >= http.StatusOK && code <= http.StatusPartialContent
if !isSuccessCode { if !isSuccessCode {
Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code)) Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...)
} }
return isSuccessCode return isSuccessCode
@@ -54,12 +54,12 @@ func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, valu
} }
code, err := httpCode(handler, method, url, values) code, err := httpCode(handler, method, url, values)
if err != nil { if err != nil {
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...)
} }
isRedirectCode := code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect isRedirectCode := code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect
if !isRedirectCode { if !isRedirectCode {
Fail(t, fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code)) Fail(t, fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...)
} }
return isRedirectCode return isRedirectCode
@@ -76,12 +76,12 @@ func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values
} }
code, err := httpCode(handler, method, url, values) code, err := httpCode(handler, method, url, values)
if err != nil { if err != nil {
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...)
} }
isErrorCode := code >= http.StatusBadRequest isErrorCode := code >= http.StatusBadRequest
if !isErrorCode { if !isErrorCode {
Fail(t, fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code)) Fail(t, fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...)
} }
return isErrorCode return isErrorCode
@@ -98,12 +98,12 @@ func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method, url string, va
} }
code, err := httpCode(handler, method, url, values) code, err := httpCode(handler, method, url, values)
if err != nil { if err != nil {
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...)
} }
successful := code == statuscode successful := code == statuscode
if !successful { if !successful {
Fail(t, fmt.Sprintf("Expected HTTP status code %d for %q but received %d", statuscode, url+"?"+values.Encode(), code)) Fail(t, fmt.Sprintf("Expected HTTP status code %d for %q but received %d", statuscode, url+"?"+values.Encode(), code), msgAndArgs...)
} }
return successful return successful
@@ -113,7 +113,10 @@ func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method, url string, va
// empty string if building a new request fails. // empty string if building a new request fails.
func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string { func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string {
w := httptest.NewRecorder() w := httptest.NewRecorder()
req, err := http.NewRequest(method, url+"?"+values.Encode(), nil) if len(values) > 0 {
url += "?" + values.Encode()
}
req, err := http.NewRequest(method, url, http.NoBody)
if err != nil { if err != nil {
return "" return ""
} }
@@ -135,7 +138,7 @@ func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string,
contains := strings.Contains(body, fmt.Sprint(str)) contains := strings.Contains(body, fmt.Sprint(str))
if !contains { if !contains {
Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)) Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body), msgAndArgs...)
} }
return contains return contains
@@ -155,7 +158,7 @@ func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url strin
contains := strings.Contains(body, fmt.Sprint(str)) contains := strings.Contains(body, fmt.Sprint(str))
if contains { if contains {
Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)) Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body), msgAndArgs...)
} }
return !contains return !contains
+47 -18
View File
@@ -1,7 +1,4 @@
/* // Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT.
* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen
* THIS FILE MUST NOT BE EDITED BY HAND
*/
package require package require
@@ -235,7 +232,7 @@ func EqualExportedValuesf(t TestingT, expected interface{}, actual interface{},
t.FailNow() t.FailNow()
} }
// EqualValues asserts that two objects are equal or convertable to the same types // EqualValues asserts that two objects are equal or convertible to the same types
// and equal. // and equal.
// //
// assert.EqualValues(t, uint32(123), int32(123)) // assert.EqualValues(t, uint32(123), int32(123))
@@ -249,7 +246,7 @@ func EqualValues(t TestingT, expected interface{}, actual interface{}, msgAndArg
t.FailNow() t.FailNow()
} }
// EqualValuesf asserts that two objects are equal or convertable to the same types // EqualValuesf asserts that two objects are equal or convertible to the same types
// and equal. // and equal.
// //
// assert.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted") // assert.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted")
@@ -1546,6 +1543,32 @@ func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interf
t.FailNow() t.FailNow()
} }
// NotImplements asserts that an object does not implement the specified interface.
//
// assert.NotImplements(t, (*MyInterface)(nil), new(MyObject))
func NotImplements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
}
if assert.NotImplements(t, interfaceObject, object, msgAndArgs...) {
return
}
t.FailNow()
}
// NotImplementsf asserts that an object does not implement the specified interface.
//
// assert.NotImplementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted")
func NotImplementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
}
if assert.NotImplementsf(t, interfaceObject, object, msg, args...) {
return
}
t.FailNow()
}
// NotNil asserts that the specified object is not nil. // NotNil asserts that the specified object is not nil.
// //
// assert.NotNil(t, err) // assert.NotNil(t, err)
@@ -1658,10 +1681,12 @@ func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string,
t.FailNow() t.FailNow()
} }
// NotSubset asserts that the specified list(array, slice...) contains not all // NotSubset asserts that the specified list(array, slice...) or map does NOT
// elements given in the specified subset(array, slice...). // contain all elements given in the specified subset list(array, slice...) or
// map.
// //
// assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") // assert.NotSubset(t, [1, 3, 4], [1, 2])
// assert.NotSubset(t, {"x": 1, "y": 2}, {"z": 3})
func NotSubset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) { func NotSubset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok { if h, ok := t.(tHelper); ok {
h.Helper() h.Helper()
@@ -1672,10 +1697,12 @@ func NotSubset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...i
t.FailNow() t.FailNow()
} }
// NotSubsetf asserts that the specified list(array, slice...) contains not all // NotSubsetf asserts that the specified list(array, slice...) or map does NOT
// elements given in the specified subset(array, slice...). // contain all elements given in the specified subset list(array, slice...) or
// map.
// //
// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") // assert.NotSubsetf(t, [1, 3, 4], [1, 2], "error message %s", "formatted")
// assert.NotSubsetf(t, {"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted")
func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) { func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok { if h, ok := t.(tHelper); ok {
h.Helper() h.Helper()
@@ -1880,10 +1907,11 @@ func Samef(t TestingT, expected interface{}, actual interface{}, msg string, arg
t.FailNow() t.FailNow()
} }
// Subset asserts that the specified list(array, slice...) contains all // Subset asserts that the specified list(array, slice...) or map contains all
// elements given in the specified subset(array, slice...). // elements given in the specified subset list(array, slice...) or map.
// //
// assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") // assert.Subset(t, [1, 2, 3], [1, 2])
// assert.Subset(t, {"x": 1, "y": 2}, {"x": 1})
func Subset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) { func Subset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok { if h, ok := t.(tHelper); ok {
h.Helper() h.Helper()
@@ -1894,10 +1922,11 @@ func Subset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...inte
t.FailNow() t.FailNow()
} }
// Subsetf asserts that the specified list(array, slice...) contains all // Subsetf asserts that the specified list(array, slice...) or map contains all
// elements given in the specified subset(array, slice...). // elements given in the specified subset list(array, slice...) or map.
// //
// assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") // assert.Subsetf(t, [1, 2, 3], [1, 2], "error message %s", "formatted")
// assert.Subsetf(t, {"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted")
func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) { func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok { if h, ok := t.(tHelper); ok {
h.Helper() h.Helper()
+41 -18
View File
@@ -1,7 +1,4 @@
/* // Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT.
* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen
* THIS FILE MUST NOT BE EDITED BY HAND
*/
package require package require
@@ -190,7 +187,7 @@ func (a *Assertions) EqualExportedValuesf(expected interface{}, actual interface
EqualExportedValuesf(a.t, expected, actual, msg, args...) EqualExportedValuesf(a.t, expected, actual, msg, args...)
} }
// EqualValues asserts that two objects are equal or convertable to the same types // EqualValues asserts that two objects are equal or convertible to the same types
// and equal. // and equal.
// //
// a.EqualValues(uint32(123), int32(123)) // a.EqualValues(uint32(123), int32(123))
@@ -201,7 +198,7 @@ func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAn
EqualValues(a.t, expected, actual, msgAndArgs...) EqualValues(a.t, expected, actual, msgAndArgs...)
} }
// EqualValuesf asserts that two objects are equal or convertable to the same types // EqualValuesf asserts that two objects are equal or convertible to the same types
// and equal. // and equal.
// //
// a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted") // a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted")
@@ -1222,6 +1219,26 @@ func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...in
NotErrorIsf(a.t, err, target, msg, args...) NotErrorIsf(a.t, err, target, msg, args...)
} }
// NotImplements asserts that an object does not implement the specified interface.
//
// a.NotImplements((*MyInterface)(nil), new(MyObject))
func (a *Assertions) NotImplements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
NotImplements(a.t, interfaceObject, object, msgAndArgs...)
}
// NotImplementsf asserts that an object does not implement the specified interface.
//
// a.NotImplementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted")
func (a *Assertions) NotImplementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
}
NotImplementsf(a.t, interfaceObject, object, msg, args...)
}
// NotNil asserts that the specified object is not nil. // NotNil asserts that the specified object is not nil.
// //
// a.NotNil(err) // a.NotNil(err)
@@ -1310,10 +1327,12 @@ func (a *Assertions) NotSamef(expected interface{}, actual interface{}, msg stri
NotSamef(a.t, expected, actual, msg, args...) NotSamef(a.t, expected, actual, msg, args...)
} }
// NotSubset asserts that the specified list(array, slice...) contains not all // NotSubset asserts that the specified list(array, slice...) or map does NOT
// elements given in the specified subset(array, slice...). // contain all elements given in the specified subset list(array, slice...) or
// map.
// //
// a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") // a.NotSubset([1, 3, 4], [1, 2])
// a.NotSubset({"x": 1, "y": 2}, {"z": 3})
func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) { func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) {
if h, ok := a.t.(tHelper); ok { if h, ok := a.t.(tHelper); ok {
h.Helper() h.Helper()
@@ -1321,10 +1340,12 @@ func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs
NotSubset(a.t, list, subset, msgAndArgs...) NotSubset(a.t, list, subset, msgAndArgs...)
} }
// NotSubsetf asserts that the specified list(array, slice...) contains not all // NotSubsetf asserts that the specified list(array, slice...) or map does NOT
// elements given in the specified subset(array, slice...). // contain all elements given in the specified subset list(array, slice...) or
// map.
// //
// a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") // a.NotSubsetf([1, 3, 4], [1, 2], "error message %s", "formatted")
// a.NotSubsetf({"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted")
func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) { func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) {
if h, ok := a.t.(tHelper); ok { if h, ok := a.t.(tHelper); ok {
h.Helper() h.Helper()
@@ -1484,10 +1505,11 @@ func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string,
Samef(a.t, expected, actual, msg, args...) Samef(a.t, expected, actual, msg, args...)
} }
// Subset asserts that the specified list(array, slice...) contains all // Subset asserts that the specified list(array, slice...) or map contains all
// elements given in the specified subset(array, slice...). // elements given in the specified subset list(array, slice...) or map.
// //
// a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") // a.Subset([1, 2, 3], [1, 2])
// a.Subset({"x": 1, "y": 2}, {"x": 1})
func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) { func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) {
if h, ok := a.t.(tHelper); ok { if h, ok := a.t.(tHelper); ok {
h.Helper() h.Helper()
@@ -1495,10 +1517,11 @@ func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...
Subset(a.t, list, subset, msgAndArgs...) Subset(a.t, list, subset, msgAndArgs...)
} }
// Subsetf asserts that the specified list(array, slice...) contains all // Subsetf asserts that the specified list(array, slice...) or map contains all
// elements given in the specified subset(array, slice...). // elements given in the specified subset list(array, slice...) or map.
// //
// a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") // a.Subsetf([1, 2, 3], [1, 2], "error message %s", "formatted")
// a.Subsetf({"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted")
func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) { func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) {
if h, ok := a.t.(tHelper); ok { if h, ok := a.t.(tHelper); ok {
h.Helper() h.Helper()
+6 -8
View File
@@ -19,15 +19,14 @@
#define POLY1305_MUL(h0, h1, h2, r0, r1, t0, t1, t2, t3, t4, t5) \ #define POLY1305_MUL(h0, h1, h2, r0, r1, t0, t1, t2, t3, t4, t5) \
MULLD r0, h0, t0; \ MULLD r0, h0, t0; \
MULLD r0, h1, t4; \
MULHDU r0, h0, t1; \ MULHDU r0, h0, t1; \
MULLD r0, h1, t4; \
MULHDU r0, h1, t5; \ MULHDU r0, h1, t5; \
ADDC t4, t1, t1; \ ADDC t4, t1, t1; \
MULLD r0, h2, t2; \ MULLD r0, h2, t2; \
ADDZE t5; \
MULHDU r1, h0, t4; \ MULHDU r1, h0, t4; \
MULLD r1, h0, h0; \ MULLD r1, h0, h0; \
ADD t5, t2, t2; \ ADDE t5, t2, t2; \
ADDC h0, t1, t1; \ ADDC h0, t1, t1; \
MULLD h2, r1, t3; \ MULLD h2, r1, t3; \
ADDZE t4, h0; \ ADDZE t4, h0; \
@@ -37,13 +36,11 @@
ADDE t5, t3, t3; \ ADDE t5, t3, t3; \
ADDC h0, t2, t2; \ ADDC h0, t2, t2; \
MOVD $-4, t4; \ MOVD $-4, t4; \
MOVD t0, h0; \
MOVD t1, h1; \
ADDZE t3; \ ADDZE t3; \
ANDCC $3, t2, h2; \ RLDICL $0, t2, $62, h2; \
AND t2, t4, t0; \ AND t2, t4, h0; \
ADDC t0, h0, h0; \ ADDC t0, h0, h0; \
ADDE t3, h1, h1; \ ADDE t3, t1, h1; \
SLD $62, t3, t4; \ SLD $62, t3, t4; \
SRD $2, t2; \ SRD $2, t2; \
ADDZE h2; \ ADDZE h2; \
@@ -75,6 +72,7 @@ TEXT ·update(SB), $0-32
loop: loop:
POLY1305_ADD(R4, R8, R9, R10, R20, R21, R22) POLY1305_ADD(R4, R8, R9, R10, R20, R21, R22)
PCALIGN $16
multiply: multiply:
POLY1305_MUL(R8, R9, R10, R11, R12, R16, R17, R18, R14, R20, R21) POLY1305_MUL(R8, R9, R10, R11, R12, R16, R17, R18, R14, R20, R21)
ADD $-16, R5 ADD $-16, R5
+1 -1
View File
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos) && go1.9 //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
package unix package unix
+1 -1
View File
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build darwin && go1.12 //go:build darwin
package unix package unix
+7 -5
View File
@@ -13,6 +13,7 @@
package unix package unix
import ( import (
"errors"
"sync" "sync"
"unsafe" "unsafe"
) )
@@ -169,25 +170,26 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
func Uname(uname *Utsname) error { func Uname(uname *Utsname) error {
mib := []_C_int{CTL_KERN, KERN_OSTYPE} mib := []_C_int{CTL_KERN, KERN_OSTYPE}
n := unsafe.Sizeof(uname.Sysname) n := unsafe.Sizeof(uname.Sysname)
if err := sysctl(mib, &uname.Sysname[0], &n, nil, 0); err != nil { // Suppress ENOMEM errors to be compatible with the C library __xuname() implementation.
if err := sysctl(mib, &uname.Sysname[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) {
return err return err
} }
mib = []_C_int{CTL_KERN, KERN_HOSTNAME} mib = []_C_int{CTL_KERN, KERN_HOSTNAME}
n = unsafe.Sizeof(uname.Nodename) n = unsafe.Sizeof(uname.Nodename)
if err := sysctl(mib, &uname.Nodename[0], &n, nil, 0); err != nil { if err := sysctl(mib, &uname.Nodename[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) {
return err return err
} }
mib = []_C_int{CTL_KERN, KERN_OSRELEASE} mib = []_C_int{CTL_KERN, KERN_OSRELEASE}
n = unsafe.Sizeof(uname.Release) n = unsafe.Sizeof(uname.Release)
if err := sysctl(mib, &uname.Release[0], &n, nil, 0); err != nil { if err := sysctl(mib, &uname.Release[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) {
return err return err
} }
mib = []_C_int{CTL_KERN, KERN_VERSION} mib = []_C_int{CTL_KERN, KERN_VERSION}
n = unsafe.Sizeof(uname.Version) n = unsafe.Sizeof(uname.Version)
if err := sysctl(mib, &uname.Version[0], &n, nil, 0); err != nil { if err := sysctl(mib, &uname.Version[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) {
return err return err
} }
@@ -205,7 +207,7 @@ func Uname(uname *Utsname) error {
mib = []_C_int{CTL_HW, HW_MACHINE} mib = []_C_int{CTL_HW, HW_MACHINE}
n = unsafe.Sizeof(uname.Machine) n = unsafe.Sizeof(uname.Machine)
if err := sysctl(mib, &uname.Machine[0], &n, nil, 0); err != nil { if err := sysctl(mib, &uname.Machine[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) {
return err return err
} }
+99
View File
@@ -1849,6 +1849,105 @@ func Dup2(oldfd, newfd int) error {
//sys Fsmount(fd int, flags int, mountAttrs int) (fsfd int, err error) //sys Fsmount(fd int, flags int, mountAttrs int) (fsfd int, err error)
//sys Fsopen(fsName string, flags int) (fd int, err error) //sys Fsopen(fsName string, flags int) (fd int, err error)
//sys Fspick(dirfd int, pathName string, flags int) (fd int, err error) //sys Fspick(dirfd int, pathName string, flags int) (fd int, err error)
//sys fsconfig(fd int, cmd uint, key *byte, value *byte, aux int) (err error)
func fsconfigCommon(fd int, cmd uint, key string, value *byte, aux int) (err error) {
var keyp *byte
if keyp, err = BytePtrFromString(key); err != nil {
return
}
return fsconfig(fd, cmd, keyp, value, aux)
}
// FsconfigSetFlag is equivalent to fsconfig(2) called
// with cmd == FSCONFIG_SET_FLAG.
//
// fd is the filesystem context to act upon.
// key the parameter key to set.
func FsconfigSetFlag(fd int, key string) (err error) {
return fsconfigCommon(fd, FSCONFIG_SET_FLAG, key, nil, 0)
}
// FsconfigSetString is equivalent to fsconfig(2) called
// with cmd == FSCONFIG_SET_STRING.
//
// fd is the filesystem context to act upon.
// key the parameter key to set.
// value is the parameter value to set.
func FsconfigSetString(fd int, key string, value string) (err error) {
var valuep *byte
if valuep, err = BytePtrFromString(value); err != nil {
return
}
return fsconfigCommon(fd, FSCONFIG_SET_STRING, key, valuep, 0)
}
// FsconfigSetBinary is equivalent to fsconfig(2) called
// with cmd == FSCONFIG_SET_BINARY.
//
// fd is the filesystem context to act upon.
// key the parameter key to set.
// value is the parameter value to set.
func FsconfigSetBinary(fd int, key string, value []byte) (err error) {
if len(value) == 0 {
return EINVAL
}
return fsconfigCommon(fd, FSCONFIG_SET_BINARY, key, &value[0], len(value))
}
// FsconfigSetPath is equivalent to fsconfig(2) called
// with cmd == FSCONFIG_SET_PATH.
//
// fd is the filesystem context to act upon.
// key the parameter key to set.
// path is a non-empty path for specified key.
// atfd is a file descriptor at which to start lookup from or AT_FDCWD.
func FsconfigSetPath(fd int, key string, path string, atfd int) (err error) {
var valuep *byte
if valuep, err = BytePtrFromString(path); err != nil {
return
}
return fsconfigCommon(fd, FSCONFIG_SET_PATH, key, valuep, atfd)
}
// FsconfigSetPathEmpty is equivalent to fsconfig(2) called
// with cmd == FSCONFIG_SET_PATH_EMPTY. The same as
// FconfigSetPath but with AT_PATH_EMPTY implied.
func FsconfigSetPathEmpty(fd int, key string, path string, atfd int) (err error) {
var valuep *byte
if valuep, err = BytePtrFromString(path); err != nil {
return
}
return fsconfigCommon(fd, FSCONFIG_SET_PATH_EMPTY, key, valuep, atfd)
}
// FsconfigSetFd is equivalent to fsconfig(2) called
// with cmd == FSCONFIG_SET_FD.
//
// fd is the filesystem context to act upon.
// key the parameter key to set.
// value is a file descriptor to be assigned to specified key.
func FsconfigSetFd(fd int, key string, value int) (err error) {
return fsconfigCommon(fd, FSCONFIG_SET_FD, key, nil, value)
}
// FsconfigCreate is equivalent to fsconfig(2) called
// with cmd == FSCONFIG_CMD_CREATE.
//
// fd is the filesystem context to act upon.
func FsconfigCreate(fd int) (err error) {
return fsconfig(fd, FSCONFIG_CMD_CREATE, nil, nil, 0)
}
// FsconfigReconfigure is equivalent to fsconfig(2) called
// with cmd == FSCONFIG_CMD_RECONFIGURE.
//
// fd is the filesystem context to act upon.
func FsconfigReconfigure(fd int) (err error) {
return fsconfig(fd, FSCONFIG_CMD_RECONFIGURE, nil, nil, 0)
}
//sys Getdents(fd int, buf []byte) (n int, err error) = SYS_GETDENTS64 //sys Getdents(fd int, buf []byte) (n int, err error) = SYS_GETDENTS64
//sysnb Getpgid(pid int) (pgid int, err error) //sysnb Getpgid(pid int) (pgid int, err error)
+10
View File
@@ -906,6 +906,16 @@ func Fspick(dirfd int, pathName string, flags int) (fd int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func fsconfig(fd int, cmd uint, key *byte, value *byte, aux int) (err error) {
_, _, e1 := Syscall6(SYS_FSCONFIG, uintptr(fd), uintptr(cmd), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(value)), uintptr(aux), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Getdents(fd int, buf []byte) (n int, err error) { func Getdents(fd int, buf []byte) (n int, err error) {
var _p0 unsafe.Pointer var _p0 unsafe.Pointer
if len(buf) > 0 { if len(buf) > 0 {
+60
View File
@@ -836,6 +836,15 @@ const (
FSPICK_EMPTY_PATH = 0x8 FSPICK_EMPTY_PATH = 0x8
FSMOUNT_CLOEXEC = 0x1 FSMOUNT_CLOEXEC = 0x1
FSCONFIG_SET_FLAG = 0x0
FSCONFIG_SET_STRING = 0x1
FSCONFIG_SET_BINARY = 0x2
FSCONFIG_SET_PATH = 0x3
FSCONFIG_SET_PATH_EMPTY = 0x4
FSCONFIG_SET_FD = 0x5
FSCONFIG_CMD_CREATE = 0x6
FSCONFIG_CMD_RECONFIGURE = 0x7
) )
type OpenHow struct { type OpenHow struct {
@@ -1550,6 +1559,7 @@ const (
IFLA_DEVLINK_PORT = 0x3e IFLA_DEVLINK_PORT = 0x3e
IFLA_GSO_IPV4_MAX_SIZE = 0x3f IFLA_GSO_IPV4_MAX_SIZE = 0x3f
IFLA_GRO_IPV4_MAX_SIZE = 0x40 IFLA_GRO_IPV4_MAX_SIZE = 0x40
IFLA_DPLL_PIN = 0x41
IFLA_PROTO_DOWN_REASON_UNSPEC = 0x0 IFLA_PROTO_DOWN_REASON_UNSPEC = 0x0
IFLA_PROTO_DOWN_REASON_MASK = 0x1 IFLA_PROTO_DOWN_REASON_MASK = 0x1
IFLA_PROTO_DOWN_REASON_VALUE = 0x2 IFLA_PROTO_DOWN_REASON_VALUE = 0x2
@@ -1565,6 +1575,7 @@ const (
IFLA_INET6_ICMP6STATS = 0x6 IFLA_INET6_ICMP6STATS = 0x6
IFLA_INET6_TOKEN = 0x7 IFLA_INET6_TOKEN = 0x7
IFLA_INET6_ADDR_GEN_MODE = 0x8 IFLA_INET6_ADDR_GEN_MODE = 0x8
IFLA_INET6_RA_MTU = 0x9
IFLA_BR_UNSPEC = 0x0 IFLA_BR_UNSPEC = 0x0
IFLA_BR_FORWARD_DELAY = 0x1 IFLA_BR_FORWARD_DELAY = 0x1
IFLA_BR_HELLO_TIME = 0x2 IFLA_BR_HELLO_TIME = 0x2
@@ -1612,6 +1623,9 @@ const (
IFLA_BR_MCAST_MLD_VERSION = 0x2c IFLA_BR_MCAST_MLD_VERSION = 0x2c
IFLA_BR_VLAN_STATS_PER_PORT = 0x2d IFLA_BR_VLAN_STATS_PER_PORT = 0x2d
IFLA_BR_MULTI_BOOLOPT = 0x2e IFLA_BR_MULTI_BOOLOPT = 0x2e
IFLA_BR_MCAST_QUERIER_STATE = 0x2f
IFLA_BR_FDB_N_LEARNED = 0x30
IFLA_BR_FDB_MAX_LEARNED = 0x31
IFLA_BRPORT_UNSPEC = 0x0 IFLA_BRPORT_UNSPEC = 0x0
IFLA_BRPORT_STATE = 0x1 IFLA_BRPORT_STATE = 0x1
IFLA_BRPORT_PRIORITY = 0x2 IFLA_BRPORT_PRIORITY = 0x2
@@ -1649,6 +1663,14 @@ const (
IFLA_BRPORT_BACKUP_PORT = 0x22 IFLA_BRPORT_BACKUP_PORT = 0x22
IFLA_BRPORT_MRP_RING_OPEN = 0x23 IFLA_BRPORT_MRP_RING_OPEN = 0x23
IFLA_BRPORT_MRP_IN_OPEN = 0x24 IFLA_BRPORT_MRP_IN_OPEN = 0x24
IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT = 0x25
IFLA_BRPORT_MCAST_EHT_HOSTS_CNT = 0x26
IFLA_BRPORT_LOCKED = 0x27
IFLA_BRPORT_MAB = 0x28
IFLA_BRPORT_MCAST_N_GROUPS = 0x29
IFLA_BRPORT_MCAST_MAX_GROUPS = 0x2a
IFLA_BRPORT_NEIGH_VLAN_SUPPRESS = 0x2b
IFLA_BRPORT_BACKUP_NHID = 0x2c
IFLA_INFO_UNSPEC = 0x0 IFLA_INFO_UNSPEC = 0x0
IFLA_INFO_KIND = 0x1 IFLA_INFO_KIND = 0x1
IFLA_INFO_DATA = 0x2 IFLA_INFO_DATA = 0x2
@@ -1670,6 +1692,9 @@ const (
IFLA_MACVLAN_MACADDR = 0x4 IFLA_MACVLAN_MACADDR = 0x4
IFLA_MACVLAN_MACADDR_DATA = 0x5 IFLA_MACVLAN_MACADDR_DATA = 0x5
IFLA_MACVLAN_MACADDR_COUNT = 0x6 IFLA_MACVLAN_MACADDR_COUNT = 0x6
IFLA_MACVLAN_BC_QUEUE_LEN = 0x7
IFLA_MACVLAN_BC_QUEUE_LEN_USED = 0x8
IFLA_MACVLAN_BC_CUTOFF = 0x9
IFLA_VRF_UNSPEC = 0x0 IFLA_VRF_UNSPEC = 0x0
IFLA_VRF_TABLE = 0x1 IFLA_VRF_TABLE = 0x1
IFLA_VRF_PORT_UNSPEC = 0x0 IFLA_VRF_PORT_UNSPEC = 0x0
@@ -1693,9 +1718,22 @@ const (
IFLA_XFRM_UNSPEC = 0x0 IFLA_XFRM_UNSPEC = 0x0
IFLA_XFRM_LINK = 0x1 IFLA_XFRM_LINK = 0x1
IFLA_XFRM_IF_ID = 0x2 IFLA_XFRM_IF_ID = 0x2
IFLA_XFRM_COLLECT_METADATA = 0x3
IFLA_IPVLAN_UNSPEC = 0x0 IFLA_IPVLAN_UNSPEC = 0x0
IFLA_IPVLAN_MODE = 0x1 IFLA_IPVLAN_MODE = 0x1
IFLA_IPVLAN_FLAGS = 0x2 IFLA_IPVLAN_FLAGS = 0x2
NETKIT_NEXT = -0x1
NETKIT_PASS = 0x0
NETKIT_DROP = 0x2
NETKIT_REDIRECT = 0x7
NETKIT_L2 = 0x0
NETKIT_L3 = 0x1
IFLA_NETKIT_UNSPEC = 0x0
IFLA_NETKIT_PEER_INFO = 0x1
IFLA_NETKIT_PRIMARY = 0x2
IFLA_NETKIT_POLICY = 0x3
IFLA_NETKIT_PEER_POLICY = 0x4
IFLA_NETKIT_MODE = 0x5
IFLA_VXLAN_UNSPEC = 0x0 IFLA_VXLAN_UNSPEC = 0x0
IFLA_VXLAN_ID = 0x1 IFLA_VXLAN_ID = 0x1
IFLA_VXLAN_GROUP = 0x2 IFLA_VXLAN_GROUP = 0x2
@@ -1726,6 +1764,8 @@ const (
IFLA_VXLAN_GPE = 0x1b IFLA_VXLAN_GPE = 0x1b
IFLA_VXLAN_TTL_INHERIT = 0x1c IFLA_VXLAN_TTL_INHERIT = 0x1c
IFLA_VXLAN_DF = 0x1d IFLA_VXLAN_DF = 0x1d
IFLA_VXLAN_VNIFILTER = 0x1e
IFLA_VXLAN_LOCALBYPASS = 0x1f
IFLA_GENEVE_UNSPEC = 0x0 IFLA_GENEVE_UNSPEC = 0x0
IFLA_GENEVE_ID = 0x1 IFLA_GENEVE_ID = 0x1
IFLA_GENEVE_REMOTE = 0x2 IFLA_GENEVE_REMOTE = 0x2
@@ -1740,6 +1780,7 @@ const (
IFLA_GENEVE_LABEL = 0xb IFLA_GENEVE_LABEL = 0xb
IFLA_GENEVE_TTL_INHERIT = 0xc IFLA_GENEVE_TTL_INHERIT = 0xc
IFLA_GENEVE_DF = 0xd IFLA_GENEVE_DF = 0xd
IFLA_GENEVE_INNER_PROTO_INHERIT = 0xe
IFLA_BAREUDP_UNSPEC = 0x0 IFLA_BAREUDP_UNSPEC = 0x0
IFLA_BAREUDP_PORT = 0x1 IFLA_BAREUDP_PORT = 0x1
IFLA_BAREUDP_ETHERTYPE = 0x2 IFLA_BAREUDP_ETHERTYPE = 0x2
@@ -1752,6 +1793,8 @@ const (
IFLA_GTP_FD1 = 0x2 IFLA_GTP_FD1 = 0x2
IFLA_GTP_PDP_HASHSIZE = 0x3 IFLA_GTP_PDP_HASHSIZE = 0x3
IFLA_GTP_ROLE = 0x4 IFLA_GTP_ROLE = 0x4
IFLA_GTP_CREATE_SOCKETS = 0x5
IFLA_GTP_RESTART_COUNT = 0x6
IFLA_BOND_UNSPEC = 0x0 IFLA_BOND_UNSPEC = 0x0
IFLA_BOND_MODE = 0x1 IFLA_BOND_MODE = 0x1
IFLA_BOND_ACTIVE_SLAVE = 0x2 IFLA_BOND_ACTIVE_SLAVE = 0x2
@@ -1781,6 +1824,9 @@ const (
IFLA_BOND_AD_ACTOR_SYSTEM = 0x1a IFLA_BOND_AD_ACTOR_SYSTEM = 0x1a
IFLA_BOND_TLB_DYNAMIC_LB = 0x1b IFLA_BOND_TLB_DYNAMIC_LB = 0x1b
IFLA_BOND_PEER_NOTIF_DELAY = 0x1c IFLA_BOND_PEER_NOTIF_DELAY = 0x1c
IFLA_BOND_AD_LACP_ACTIVE = 0x1d
IFLA_BOND_MISSED_MAX = 0x1e
IFLA_BOND_NS_IP6_TARGET = 0x1f
IFLA_BOND_AD_INFO_UNSPEC = 0x0 IFLA_BOND_AD_INFO_UNSPEC = 0x0
IFLA_BOND_AD_INFO_AGGREGATOR = 0x1 IFLA_BOND_AD_INFO_AGGREGATOR = 0x1
IFLA_BOND_AD_INFO_NUM_PORTS = 0x2 IFLA_BOND_AD_INFO_NUM_PORTS = 0x2
@@ -1796,6 +1842,7 @@ const (
IFLA_BOND_SLAVE_AD_AGGREGATOR_ID = 0x6 IFLA_BOND_SLAVE_AD_AGGREGATOR_ID = 0x6
IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE = 0x7 IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE = 0x7
IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE = 0x8 IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE = 0x8
IFLA_BOND_SLAVE_PRIO = 0x9
IFLA_VF_INFO_UNSPEC = 0x0 IFLA_VF_INFO_UNSPEC = 0x0
IFLA_VF_INFO = 0x1 IFLA_VF_INFO = 0x1
IFLA_VF_UNSPEC = 0x0 IFLA_VF_UNSPEC = 0x0
@@ -1854,8 +1901,16 @@ const (
IFLA_STATS_LINK_XSTATS_SLAVE = 0x3 IFLA_STATS_LINK_XSTATS_SLAVE = 0x3
IFLA_STATS_LINK_OFFLOAD_XSTATS = 0x4 IFLA_STATS_LINK_OFFLOAD_XSTATS = 0x4
IFLA_STATS_AF_SPEC = 0x5 IFLA_STATS_AF_SPEC = 0x5
IFLA_STATS_GETSET_UNSPEC = 0x0
IFLA_STATS_GET_FILTERS = 0x1
IFLA_STATS_SET_OFFLOAD_XSTATS_L3_STATS = 0x2
IFLA_OFFLOAD_XSTATS_UNSPEC = 0x0 IFLA_OFFLOAD_XSTATS_UNSPEC = 0x0
IFLA_OFFLOAD_XSTATS_CPU_HIT = 0x1 IFLA_OFFLOAD_XSTATS_CPU_HIT = 0x1
IFLA_OFFLOAD_XSTATS_HW_S_INFO = 0x2
IFLA_OFFLOAD_XSTATS_L3_STATS = 0x3
IFLA_OFFLOAD_XSTATS_HW_S_INFO_UNSPEC = 0x0
IFLA_OFFLOAD_XSTATS_HW_S_INFO_REQUEST = 0x1
IFLA_OFFLOAD_XSTATS_HW_S_INFO_USED = 0x2
IFLA_XDP_UNSPEC = 0x0 IFLA_XDP_UNSPEC = 0x0
IFLA_XDP_FD = 0x1 IFLA_XDP_FD = 0x1
IFLA_XDP_ATTACHED = 0x2 IFLA_XDP_ATTACHED = 0x2
@@ -1885,6 +1940,11 @@ const (
IFLA_RMNET_UNSPEC = 0x0 IFLA_RMNET_UNSPEC = 0x0
IFLA_RMNET_MUX_ID = 0x1 IFLA_RMNET_MUX_ID = 0x1
IFLA_RMNET_FLAGS = 0x2 IFLA_RMNET_FLAGS = 0x2
IFLA_MCTP_UNSPEC = 0x0
IFLA_MCTP_NET = 0x1
IFLA_DSA_UNSPEC = 0x0
IFLA_DSA_CONDUIT = 0x1
IFLA_DSA_MASTER = 0x1
) )
const ( const (
Generated Vendored
+10 -10
View File
@@ -8,7 +8,7 @@ github.com/Microsoft/go-winio/internal/fs
github.com/Microsoft/go-winio/internal/socket github.com/Microsoft/go-winio/internal/socket
github.com/Microsoft/go-winio/internal/stringbuffer github.com/Microsoft/go-winio/internal/stringbuffer
github.com/Microsoft/go-winio/pkg/guid github.com/Microsoft/go-winio/pkg/guid
# github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 # github.com/ProtonMail/go-crypto v1.0.0
## explicit; go 1.13 ## explicit; go 1.13
github.com/ProtonMail/go-crypto/bitcurves github.com/ProtonMail/go-crypto/bitcurves
github.com/ProtonMail/go-crypto/brainpool github.com/ProtonMail/go-crypto/brainpool
@@ -70,7 +70,7 @@ github.com/go-git/go-billy/v5/helper/polyfill
github.com/go-git/go-billy/v5/memfs github.com/go-git/go-billy/v5/memfs
github.com/go-git/go-billy/v5/osfs github.com/go-git/go-billy/v5/osfs
github.com/go-git/go-billy/v5/util github.com/go-git/go-billy/v5/util
# github.com/go-git/go-git/v5 v5.11.0 # github.com/go-git/go-git/v5 v5.12.0
## explicit; go 1.19 ## explicit; go 1.19
github.com/go-git/go-git/v5 github.com/go-git/go-git/v5
github.com/go-git/go-git/v5/config github.com/go-git/go-git/v5/config
@@ -153,10 +153,10 @@ github.com/pkg/errors
# github.com/pmezard/go-difflib v1.0.0 # github.com/pmezard/go-difflib v1.0.0
## explicit ## explicit
github.com/pmezard/go-difflib/difflib github.com/pmezard/go-difflib/difflib
# github.com/sergi/go-diff v1.2.0 # github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3
## explicit; go 1.12 ## explicit; go 1.13
github.com/sergi/go-diff/diffmatchpatch github.com/sergi/go-diff/diffmatchpatch
# github.com/skeema/knownhosts v1.2.1 # github.com/skeema/knownhosts v1.2.2
## explicit; go 1.17 ## explicit; go 1.17
github.com/skeema/knownhosts github.com/skeema/knownhosts
# github.com/spf13/cobra v1.8.0 # github.com/spf13/cobra v1.8.0
@@ -165,14 +165,14 @@ github.com/spf13/cobra
# github.com/spf13/pflag v1.0.5 # github.com/spf13/pflag v1.0.5
## explicit; go 1.12 ## explicit; go 1.12
github.com/spf13/pflag github.com/spf13/pflag
# github.com/stretchr/testify v1.8.4 # github.com/stretchr/testify v1.9.0
## explicit; go 1.20 ## explicit; go 1.17
github.com/stretchr/testify/assert github.com/stretchr/testify/assert
github.com/stretchr/testify/require github.com/stretchr/testify/require
# github.com/xanzy/ssh-agent v0.3.3 # github.com/xanzy/ssh-agent v0.3.3
## explicit; go 1.16 ## explicit; go 1.16
github.com/xanzy/ssh-agent github.com/xanzy/ssh-agent
# golang.org/x/crypto v0.19.0 # golang.org/x/crypto v0.21.0
## explicit; go 1.18 ## explicit; go 1.18
golang.org/x/crypto/argon2 golang.org/x/crypto/argon2
golang.org/x/crypto/blake2b golang.org/x/crypto/blake2b
@@ -198,7 +198,7 @@ golang.org/x/crypto/ssh/knownhosts
# golang.org/x/mod v0.12.0 # golang.org/x/mod v0.12.0
## explicit; go 1.17 ## explicit; go 1.17
golang.org/x/mod/semver golang.org/x/mod/semver
# golang.org/x/net v0.21.0 # golang.org/x/net v0.22.0
## explicit; go 1.18 ## explicit; go 1.18
golang.org/x/net/context golang.org/x/net/context
golang.org/x/net/internal/socks golang.org/x/net/internal/socks
@@ -207,7 +207,7 @@ golang.org/x/net/proxy
## explicit; go 1.18 ## explicit; go 1.18
golang.org/x/oauth2 golang.org/x/oauth2
golang.org/x/oauth2/internal golang.org/x/oauth2/internal
# golang.org/x/sys v0.17.0 # golang.org/x/sys v0.18.0
## explicit; go 1.18 ## explicit; go 1.18
golang.org/x/sys/cpu golang.org/x/sys/cpu
golang.org/x/sys/execabs golang.org/x/sys/execabs