Compare commits
2 Commits
76a7247f1a
...
acd4997459
Author | SHA1 | Date | |
---|---|---|---|
acd4997459 | |||
55ca4468cc |
10
go.mod
10
go.mod
@ -7,8 +7,9 @@ require (
|
|||||||
github.com/adrg/xdg v0.4.0
|
github.com/adrg/xdg v0.4.0
|
||||||
github.com/alecthomas/kong v0.8.1
|
github.com/alecthomas/kong v0.8.1
|
||||||
github.com/charmbracelet/log v0.3.1
|
github.com/charmbracelet/log v0.3.1
|
||||||
|
github.com/go-git/go-billy/v5 v5.5.0
|
||||||
|
github.com/go-git/go-git/v5 v5.11.0
|
||||||
github.com/gobwas/glob v0.2.3
|
github.com/gobwas/glob v0.2.3
|
||||||
github.com/juju/errors v1.0.0
|
|
||||||
github.com/otiai10/copy v1.14.0
|
github.com/otiai10/copy v1.14.0
|
||||||
github.com/stretchr/testify v1.8.4
|
github.com/stretchr/testify v1.8.4
|
||||||
github.com/vmihailenco/msgpack/v5 v5.4.1
|
github.com/vmihailenco/msgpack/v5 v5.4.1
|
||||||
@ -19,8 +20,11 @@ require (
|
|||||||
require (
|
require (
|
||||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||||
github.com/charmbracelet/lipgloss v0.9.1 // indirect
|
github.com/charmbracelet/lipgloss v0.9.1 // 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
|
||||||
|
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||||
github.com/go-logfmt/logfmt v0.6.0 // indirect
|
github.com/go-logfmt/logfmt v0.6.0 // indirect
|
||||||
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.18 // indirect
|
github.com/mattn/go-isatty v0.0.18 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||||
@ -30,6 +34,8 @@ require (
|
|||||||
github.com/rivo/uniseg v0.2.0 // indirect
|
github.com/rivo/uniseg v0.2.0 // indirect
|
||||||
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
|
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
|
||||||
golang.org/x/sys v0.13.0 // indirect
|
golang.org/x/net v0.19.0 // indirect
|
||||||
|
golang.org/x/sys v0.15.0 // indirect
|
||||||
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
34
go.sum
34
go.sum
@ -14,19 +14,29 @@ github.com/charmbracelet/lipgloss v0.9.1 h1:PNyd3jvaJbg4jRHKWXnCj1akQm4rh8dbEzN1
|
|||||||
github.com/charmbracelet/lipgloss v0.9.1/go.mod h1:1mPmG4cxScwUQALAAnacHaigiiHB9Pmr+v1VEawJl6I=
|
github.com/charmbracelet/lipgloss v0.9.1/go.mod h1:1mPmG4cxScwUQALAAnacHaigiiHB9Pmr+v1VEawJl6I=
|
||||||
github.com/charmbracelet/log v0.3.1 h1:TjuY4OBNbxmHWSwO3tosgqs5I3biyY8sQPny/eCMTYw=
|
github.com/charmbracelet/log v0.3.1 h1:TjuY4OBNbxmHWSwO3tosgqs5I3biyY8sQPny/eCMTYw=
|
||||||
github.com/charmbracelet/log v0.3.1/go.mod h1:OR4E1hutLsax3ZKpXbgUqPtTjQfrh1pG3zwHGWuuq8g=
|
github.com/charmbracelet/log v0.3.1/go.mod h1:OR4E1hutLsax3ZKpXbgUqPtTjQfrh1pG3zwHGWuuq8g=
|
||||||
|
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
|
||||||
|
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
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/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-git/v5 v5.11.0 h1:XIZc1p+8YzypNr34itUfSvYJcv+eYdTnTvOZ2vD3cA4=
|
||||||
|
github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY=
|
||||||
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
|
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
|
||||||
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||||
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
||||||
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||||
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
|
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
|
||||||
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
|
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
|
||||||
github.com/juju/errors v1.0.0 h1:yiq7kjCLll1BiaRuNY53MGI0+EQ3rF6GB+wvboZDefM=
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||||
github.com/juju/errors v1.0.0/go.mod h1:B5x9thDqx0wIMH3+aLIMP9HjItInYWObRovoCFM5Qe8=
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||||
@ -40,15 +50,21 @@ github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
|
|||||||
github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=
|
github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=
|
||||||
github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo=
|
github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo=
|
||||||
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
|
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
|
||||||
|
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
|
||||||
|
github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M=
|
||||||
github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU=
|
github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU=
|
||||||
github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w=
|
github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w=
|
||||||
github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks=
|
github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks=
|
||||||
github.com/otiai10/mint v1.5.1/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM=
|
github.com/otiai10/mint v1.5.1/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM=
|
||||||
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
|
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/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.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||||
@ -61,15 +77,21 @@ go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA=
|
|||||||
go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
|
go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
|
||||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
|
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
|
||||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
|
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
|
||||||
|
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
|
||||||
|
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
|
||||||
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
|
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
|
||||||
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/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.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||||
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
|
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||||
|
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
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=
|
||||||
|
@ -19,18 +19,30 @@ schema = 3
|
|||||||
[mod."github.com/charmbracelet/log"]
|
[mod."github.com/charmbracelet/log"]
|
||||||
version = "v0.3.1"
|
version = "v0.3.1"
|
||||||
hash = "sha256-Er60POPID2eNrRZnBHxoI4yHn0mIKnXYftGKSslbXx0="
|
hash = "sha256-Er60POPID2eNrRZnBHxoI4yHn0mIKnXYftGKSslbXx0="
|
||||||
|
[mod."github.com/cyphar/filepath-securejoin"]
|
||||||
|
version = "v0.2.4"
|
||||||
|
hash = "sha256-heCD0xMxlwnHCHcRBgTjVexHOLyWI2zRW3E8NFKoLzk="
|
||||||
[mod."github.com/davecgh/go-spew"]
|
[mod."github.com/davecgh/go-spew"]
|
||||||
version = "v1.1.1"
|
version = "v1.1.1"
|
||||||
hash = "sha256-nhzSUrE1fCkN0+RL04N4h8jWmRFPPPWbCuDc7Ss0akI="
|
hash = "sha256-nhzSUrE1fCkN0+RL04N4h8jWmRFPPPWbCuDc7Ss0akI="
|
||||||
|
[mod."github.com/go-git/gcfg"]
|
||||||
|
version = "v1.5.1-0.20230307220236-3a3c6141e376"
|
||||||
|
hash = "sha256-f4k0gSYuo0/q3WOoTxl2eFaj7WZpdz29ih6CKc8Ude8="
|
||||||
|
[mod."github.com/go-git/go-billy/v5"]
|
||||||
|
version = "v5.5.0"
|
||||||
|
hash = "sha256-4XUoD2bOCMCdu83egb/y8kY/Fm0s1rWgPMtiahh38OQ="
|
||||||
|
[mod."github.com/go-git/go-git/v5"]
|
||||||
|
version = "v5.11.0"
|
||||||
|
hash = "sha256-2yUM/FlV+nYxacVynJCnDZeMub4Iu8JL2WBHmlnwOkE="
|
||||||
[mod."github.com/go-logfmt/logfmt"]
|
[mod."github.com/go-logfmt/logfmt"]
|
||||||
version = "v0.6.0"
|
version = "v0.6.0"
|
||||||
hash = "sha256-RtIG2qARd5sT10WQ7F3LR8YJhS8exs+KiuUiVf75bWg="
|
hash = "sha256-RtIG2qARd5sT10WQ7F3LR8YJhS8exs+KiuUiVf75bWg="
|
||||||
[mod."github.com/gobwas/glob"]
|
[mod."github.com/gobwas/glob"]
|
||||||
version = "v0.2.3"
|
version = "v0.2.3"
|
||||||
hash = "sha256-hYHMUdwxVkMOjSKjR7UWO0D0juHdI4wL8JEy5plu/Jc="
|
hash = "sha256-hYHMUdwxVkMOjSKjR7UWO0D0juHdI4wL8JEy5plu/Jc="
|
||||||
[mod."github.com/juju/errors"]
|
[mod."github.com/jbenet/go-context"]
|
||||||
version = "v1.0.0"
|
version = "v0.0.0-20150711004518-d14ea06fba99"
|
||||||
hash = "sha256-9uZ0wNf44ilzLsvXqOsmFUpNOBFAVadj6+ZH8+QMDMk="
|
hash = "sha256-VANNCWNNpARH/ILQV9sCQsBWgyL2iFT+4AHZREpxIWE="
|
||||||
[mod."github.com/lucasb-eyer/go-colorful"]
|
[mod."github.com/lucasb-eyer/go-colorful"]
|
||||||
version = "v1.2.0"
|
version = "v1.2.0"
|
||||||
hash = "sha256-Gg9dDJFCTaHrKHRR1SrJgZ8fWieJkybljybkI9x0gyE="
|
hash = "sha256-Gg9dDJFCTaHrKHRR1SrJgZ8fWieJkybljybkI9x0gyE="
|
||||||
@ -70,12 +82,18 @@ schema = 3
|
|||||||
[mod."golang.org/x/exp"]
|
[mod."golang.org/x/exp"]
|
||||||
version = "v0.0.0-20231006140011-7918f672742d"
|
version = "v0.0.0-20231006140011-7918f672742d"
|
||||||
hash = "sha256-2SO1etTQ6UCUhADR5sgvDEDLHcj77pJKCIa/8mGDbAo="
|
hash = "sha256-2SO1etTQ6UCUhADR5sgvDEDLHcj77pJKCIa/8mGDbAo="
|
||||||
|
[mod."golang.org/x/net"]
|
||||||
|
version = "v0.19.0"
|
||||||
|
hash = "sha256-3M5rKEvJx4cO/q+06cGjR5sxF5JpnUWY0+fQttrWdT4="
|
||||||
[mod."golang.org/x/sync"]
|
[mod."golang.org/x/sync"]
|
||||||
version = "v0.5.0"
|
version = "v0.5.0"
|
||||||
hash = "sha256-EAKeODSsct5HhXPmpWJfulKSCkuUu6kkDttnjyZMNcI="
|
hash = "sha256-EAKeODSsct5HhXPmpWJfulKSCkuUu6kkDttnjyZMNcI="
|
||||||
[mod."golang.org/x/sys"]
|
[mod."golang.org/x/sys"]
|
||||||
version = "v0.13.0"
|
version = "v0.15.0"
|
||||||
hash = "sha256-/+RDZ0a0oEfJ0k304VqpJpdrl2ZXa3yFlOxy4mjW7w0="
|
hash = "sha256-n7TlABF6179RzGq3gctPDKDPRtDfnwPdjNCMm8ps2KY="
|
||||||
|
[mod."gopkg.in/warnings.v0"]
|
||||||
|
version = "v0.1.2"
|
||||||
|
hash = "sha256-ATVL9yEmgYbkJ1DkltDGRn/auGAjqGOfjQyBYyUo8s8="
|
||||||
[mod."gopkg.in/yaml.v3"]
|
[mod."gopkg.in/yaml.v3"]
|
||||||
version = "v3.0.1"
|
version = "v3.0.1"
|
||||||
hash = "sha256-FqL9TKYJ0XkNwJFnq9j0VvJ5ZUU1RvH/52h/f5bkYAU="
|
hash = "sha256-FqL9TKYJ0XkNwJFnq9j0VvJ5ZUU1RvH/52h/f5bkYAU="
|
||||||
|
106
internal/cache/cache.go
vendored
106
internal/cache/cache.go
vendored
@ -10,6 +10,8 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.numtide.com/numtide/treefmt/internal/git"
|
||||||
|
|
||||||
"git.numtide.com/numtide/treefmt/internal/format"
|
"git.numtide.com/numtide/treefmt/internal/format"
|
||||||
"github.com/charmbracelet/log"
|
"github.com/charmbracelet/log"
|
||||||
|
|
||||||
@ -21,6 +23,8 @@ import (
|
|||||||
const (
|
const (
|
||||||
pathsBucket = "paths"
|
pathsBucket = "paths"
|
||||||
formattersBucket = "formatters"
|
formattersBucket = "formatters"
|
||||||
|
|
||||||
|
readBatchSize = 1024
|
||||||
)
|
)
|
||||||
|
|
||||||
// Entry represents a cache entry, indicating the last size and modified time for a file path.
|
// Entry represents a cache entry, indicating the last size and modified time for a file path.
|
||||||
@ -170,41 +174,85 @@ func putEntry(bucket *bolt.Bucket, path string, entry *Entry) error {
|
|||||||
|
|
||||||
// ChangeSet is used to walk a filesystem, starting at root, and outputting any new or changed paths using pathsCh.
|
// ChangeSet is used to walk a filesystem, starting at root, and outputting any new or changed paths using pathsCh.
|
||||||
// It determines if a path is new or has changed by comparing against cache entries.
|
// It determines if a path is new or has changed by comparing against cache entries.
|
||||||
func ChangeSet(ctx context.Context, root string, pathsCh chan<- string) error {
|
func ChangeSet(ctx context.Context, root string, gitignore bool, pathsCh chan<- string) error {
|
||||||
return db.Update(func(tx *bolt.Tx) error {
|
l := log.WithPrefix("cache")
|
||||||
bucket := tx.Bucket([]byte(pathsBucket))
|
|
||||||
|
|
||||||
return filepath.Walk(root, func(path string, info fs.FileInfo, err error) error {
|
cwd, err := os.Getwd()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("%w: failed to walk path", err)
|
return fmt.Errorf("%w: failed to get current working directory", err)
|
||||||
} else if ctx.Err() != nil {
|
}
|
||||||
return ctx.Err()
|
|
||||||
} else if info.IsDir() {
|
|
||||||
// todo what about symlinks?
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if info.Mode()&os.ModeSymlink == os.ModeSymlink {
|
if err := git.LoadIgnorePatterns(); err != nil {
|
||||||
// skip symlinks
|
return err
|
||||||
return nil
|
}
|
||||||
}
|
|
||||||
|
|
||||||
cached, err := getEntry(bucket, path)
|
var tx *bolt.Tx
|
||||||
if err != nil {
|
var bucket *bolt.Bucket
|
||||||
return err
|
var processed int
|
||||||
}
|
|
||||||
|
|
||||||
changedOrNew := cached == nil || !(cached.Modified == info.ModTime() && cached.Size == info.Size())
|
defer func() {
|
||||||
|
// close any pending read tx
|
||||||
|
if tx != nil {
|
||||||
|
_ = tx.Rollback()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
if !changedOrNew {
|
return filepath.Walk(root, func(path string, info fs.FileInfo, err error) error {
|
||||||
// no change
|
if err != nil {
|
||||||
return nil
|
return fmt.Errorf("%w: failed to walk path", err)
|
||||||
}
|
} else if ctx.Err() != nil {
|
||||||
|
return ctx.Err()
|
||||||
// pass on the path
|
} else if info.IsDir() {
|
||||||
pathsCh <- path
|
// todo what about symlinks?
|
||||||
return nil
|
return nil
|
||||||
})
|
}
|
||||||
|
|
||||||
|
// ignore symlinks
|
||||||
|
if info.Mode()&os.ModeSymlink == os.ModeSymlink {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// open a new read tx if there isn't one in progress
|
||||||
|
// we have to periodically open a new read tx to prevent writes from being blocked
|
||||||
|
if tx == nil {
|
||||||
|
tx, err = db.Begin(false)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("%w: failed to open a new read tx", err)
|
||||||
|
}
|
||||||
|
bucket = tx.Bucket([]byte(pathsBucket))
|
||||||
|
}
|
||||||
|
|
||||||
|
cached, err := getEntry(bucket, path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
changedOrNew := cached == nil || !(cached.Modified == info.ModTime() && cached.Size == info.Size())
|
||||||
|
|
||||||
|
if !changedOrNew {
|
||||||
|
// no change
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
relPath, err := filepath.Rel(cwd, path)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("%w: failed to determine relative path", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if gitignore && git.Ignore(relPath) {
|
||||||
|
l.Debugf("git ignoring '%v'", path)
|
||||||
|
} else {
|
||||||
|
// pass on the path
|
||||||
|
pathsCh <- relPath
|
||||||
|
}
|
||||||
|
|
||||||
|
// close the current tx if we have reached the batch size
|
||||||
|
processed += 1
|
||||||
|
if processed == readBatchSize {
|
||||||
|
return tx.Rollback()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ type Options struct {
|
|||||||
ConfigFile string `type:"existingfile" default:"./treefmt.toml"`
|
ConfigFile string `type:"existingfile" default:"./treefmt.toml"`
|
||||||
FailOnChange bool `help:"Exit with error if any changes were made. Useful for CI"`
|
FailOnChange bool `help:"Exit with error if any changes were made. Useful for CI"`
|
||||||
Formatters []string `help:"Specify formatters to apply. Defaults to all formatters"`
|
Formatters []string `help:"Specify formatters to apply. Defaults to all formatters"`
|
||||||
|
NoGitignore bool `help:"Ignore .gitignore files within the tree root" default:"false"`
|
||||||
TreeRoot string `type:"existingdir" default:"."`
|
TreeRoot string `type:"existingdir" default:"."`
|
||||||
Verbosity int `name:"verbose" short:"v" type:"counter" default:"0" env:"LOG_LEVEL" help:"Set the verbosity of logs e.g. -vv"`
|
Verbosity int `name:"verbose" short:"v" type:"counter" default:"0" env:"LOG_LEVEL" help:"Set the verbosity of logs e.g. -vv"`
|
||||||
|
|
||||||
|
@ -191,7 +191,7 @@ func (f *Format) Run() error {
|
|||||||
|
|
||||||
eg.Go(func() error {
|
eg.Go(func() error {
|
||||||
defer close(pathsCh)
|
defer close(pathsCh)
|
||||||
return cache.ChangeSet(ctx, Cli.TreeRoot, pathsCh)
|
return cache.ChangeSet(ctx, Cli.TreeRoot, !Cli.NoGitignore, pathsCh)
|
||||||
})
|
})
|
||||||
|
|
||||||
// listen for shutdown and call cancel if required
|
// listen for shutdown and call cancel if required
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.numtide.com/numtide/treefmt/internal/test"
|
"git.numtide.com/numtide/treefmt/internal/test"
|
||||||
@ -343,3 +344,65 @@ func TestBustCacheOnFormatterChange(t *testing.T) {
|
|||||||
as.NoError(err)
|
as.NoError(err)
|
||||||
as.Contains(string(out), "0 files changed")
|
as.Contains(string(out), "0 files changed")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGitignore(t *testing.T) {
|
||||||
|
as := require.New(t)
|
||||||
|
|
||||||
|
// capture current cwd, so we can replace it after the test is finished
|
||||||
|
cwd, err := os.Getwd()
|
||||||
|
as.NoError(err)
|
||||||
|
|
||||||
|
t.Cleanup(func() {
|
||||||
|
// return to the previous working directory
|
||||||
|
as.NoError(os.Chdir(cwd))
|
||||||
|
})
|
||||||
|
|
||||||
|
tempDir := test.TempExamples(t)
|
||||||
|
configPath := tempDir + "/treefmt.toml"
|
||||||
|
|
||||||
|
// test without any excludes
|
||||||
|
config := format.Config{
|
||||||
|
Formatters: map[string]*format.Formatter{
|
||||||
|
"echo": {
|
||||||
|
Command: "echo",
|
||||||
|
Includes: []string{"*"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// without any ignores
|
||||||
|
test.WriteConfig(t, configPath, config)
|
||||||
|
out, err := cmd(t, "-C", tempDir)
|
||||||
|
as.NoError(err)
|
||||||
|
as.Contains(string(out), fmt.Sprintf("%d files changed", 29))
|
||||||
|
|
||||||
|
// ignore elm directory from root
|
||||||
|
test.WriteGitignore(t, tempDir, []string{"elm"})
|
||||||
|
out, err = cmd(t, "-C", tempDir, "-c")
|
||||||
|
as.NoError(err)
|
||||||
|
as.Contains(string(out), fmt.Sprintf("%d files changed", 28))
|
||||||
|
|
||||||
|
// ignore a specific file from root
|
||||||
|
test.WriteGitignore(t, tempDir, []string{"elm", "go/main.go"})
|
||||||
|
out, err = cmd(t, "-C", tempDir, "-c")
|
||||||
|
as.NoError(err)
|
||||||
|
as.Contains(string(out), fmt.Sprintf("%d files changed", 27))
|
||||||
|
|
||||||
|
// Ignore a haskell file using a nested gitignore
|
||||||
|
// we add 1 file (.gitignore) and ignore 1 file so the count remains the same
|
||||||
|
test.WriteGitignore(t, path.Join(tempDir, "haskell"), []string{"Nested"})
|
||||||
|
out, err = cmd(t, "-C", tempDir, "-c")
|
||||||
|
as.NoError(err)
|
||||||
|
as.Contains(string(out), fmt.Sprintf("%d files changed", 27))
|
||||||
|
|
||||||
|
// Ignore a pattern from root
|
||||||
|
test.WriteGitignore(t, tempDir, []string{"elm", "go/main.go", "**/*.js"})
|
||||||
|
out, err = cmd(t, "-C", tempDir, "-c")
|
||||||
|
as.NoError(err)
|
||||||
|
as.Contains(string(out), fmt.Sprintf("%d files changed", 26))
|
||||||
|
|
||||||
|
// Ignore .gitignore files
|
||||||
|
out, err = cmd(t, "-C", tempDir, "-c", "--no-gitignore")
|
||||||
|
as.NoError(err)
|
||||||
|
as.Contains(string(out), fmt.Sprintf("%d files changed", 31))
|
||||||
|
}
|
||||||
|
@ -11,7 +11,7 @@ func CompileGlobs(patterns []string) ([]glob.Glob, error) {
|
|||||||
globs := make([]glob.Glob, len(patterns))
|
globs := make([]glob.Glob, len(patterns))
|
||||||
|
|
||||||
for i, pattern := range patterns {
|
for i, pattern := range patterns {
|
||||||
g, err := glob.Compile("**/" + pattern)
|
g, err := glob.Compile(pattern)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%w: failed to compile include pattern '%v'", err, pattern)
|
return nil, fmt.Errorf("%w: failed to compile include pattern '%v'", err, pattern)
|
||||||
}
|
}
|
||||||
|
38
internal/git/ignore.go
Normal file
38
internal/git/ignore.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package git
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-git/go-billy/v5/osfs"
|
||||||
|
"github.com/go-git/go-git/v5/plumbing/format/gitignore"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ignorePatterns []gitignore.Pattern
|
||||||
|
|
||||||
|
func LoadIgnorePatterns() error {
|
||||||
|
cwd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("%w: failed to get current working directory", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fs := osfs.New(cwd)
|
||||||
|
ignorePatterns, err = gitignore.ReadPatterns(fs, nil)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("%w: failed to load gitignore patterns", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Ignore(path string) bool {
|
||||||
|
split := strings.Split(path, string(os.PathSeparator))
|
||||||
|
for _, pattern := range ignorePatterns {
|
||||||
|
if pattern.Match(split, false) == gitignore.Exclude {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
@ -2,6 +2,8 @@ package test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.numtide.com/numtide/treefmt/internal/format"
|
"git.numtide.com/numtide/treefmt/internal/format"
|
||||||
@ -10,6 +12,11 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func WriteGitignore(t *testing.T, dir string, entries []string) {
|
||||||
|
data := strings.Join(entries, "\n")
|
||||||
|
require.NoError(t, os.WriteFile(path.Join(dir, ".gitignore"), []byte(data), 0o755))
|
||||||
|
}
|
||||||
|
|
||||||
func WriteConfig(t *testing.T, path string, cfg format.Config) {
|
func WriteConfig(t *testing.T, path string, cfg format.Config) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
f, err := os.Create(path)
|
f, err := os.Create(path)
|
||||||
|
Reference in New Issue
Block a user