From 092663a2f272cdcdfc7f1136a1ec3678e5fb2952 Mon Sep 17 00:00:00 2001 From: Valentin Maerten Date: Fri, 3 Apr 2026 22:35:04 +0200 Subject: [PATCH 1/6] feat: add gitignore option to exclude ignored files from sources/generates When `gitignore: true` is set at the Taskfile or task level, files matching .gitignore rules are automatically excluded from sources and generates glob resolution. This prevents rebuilds triggered by changes to files that are in .gitignore (build artifacts, generated files, etc.). Uses go-git to load .gitignore patterns including nested .gitignore files, .git/info/exclude, and global gitignore configuration. --- go.mod | 16 +++ go.sum | 41 +++++++ internal/fingerprint/gitignore.go | 60 ++++++++++ internal/fingerprint/gitignore_test.go | 127 ++++++++++++++++++++++ internal/fingerprint/glob.go | 7 +- internal/fingerprint/sources_checksum.go | 2 +- internal/fingerprint/sources_timestamp.go | 6 +- task_test.go | 49 +++++++++ taskfile/ast/task.go | 10 ++ taskfile/ast/taskfile.go | 13 ++- testdata/gitignore/.gitignore | 1 + testdata/gitignore/Taskfile.yml | 25 +++++ testdata/gitignore/source.txt | 1 + variables.go | 16 ++- watch.go | 2 +- website/src/public/schema.json | 10 ++ 16 files changed, 371 insertions(+), 15 deletions(-) create mode 100644 internal/fingerprint/gitignore.go create mode 100644 internal/fingerprint/gitignore_test.go create mode 100644 testdata/gitignore/.gitignore create mode 100644 testdata/gitignore/Taskfile.yml create mode 100644 testdata/gitignore/source.txt diff --git a/go.mod b/go.mod index e776c7697b..181964d89e 100644 --- a/go.mod +++ b/go.mod @@ -43,9 +43,12 @@ require ( cloud.google.com/go/iam v1.5.3 // indirect cloud.google.com/go/monitoring v1.24.3 // indirect cloud.google.com/go/storage v1.61.3 // indirect + dario.cat/mergo v1.0.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.55.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.55.0 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/ProtonMail/go-crypto v1.1.6 // indirect github.com/atotto/clipboard v0.1.4 // indirect github.com/aws/aws-sdk-go-v2 v1.41.5 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8 // indirect @@ -76,21 +79,30 @@ require ( github.com/charmbracelet/x/windows v0.2.2 // indirect github.com/clipperhouse/displaywidth v0.11.0 // indirect github.com/clipperhouse/uax29/v2 v2.7.0 // indirect + github.com/cloudflare/circl v1.6.3 // indirect github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 // indirect + github.com/cyphar/filepath-securejoin v0.4.1 // indirect github.com/dlclark/regexp2 v1.11.5 // indirect github.com/dustin/go-humanize v1.0.1 // indirect + github.com/emirpasic/gods v1.18.1 // indirect github.com/envoyproxy/go-control-plane/envoy v1.36.0 // indirect github.com/envoyproxy/protoc-gen-validate v1.3.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect + github.com/go-git/go-billy/v5 v5.8.0 // indirect + github.com/go-git/go-git/v5 v5.17.2 // indirect github.com/go-jose/go-jose/v4 v4.1.4 // indirect github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect github.com/google/s2a-go v0.1.9 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.14 // indirect github.com/googleapis/gax-go/v2 v2.17.0 // indirect github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.72 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-version v1.8.0 // indirect + github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect + github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/klauspost/compress v1.18.5 // indirect github.com/klauspost/cpuid/v2 v2.2.10 // indirect github.com/klauspost/pgzip v1.2.6 // indirect @@ -101,15 +113,18 @@ require ( github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/muesli/cancelreader v0.2.2 // indirect github.com/pierrec/lz4/v4 v4.1.22 // indirect + github.com/pjbgf/sha1cd v0.3.2 // indirect github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect + github.com/skeema/knownhosts v1.3.1 // indirect github.com/spiffe/go-spiffe/v2 v2.6.0 // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/u-root/u-root v0.15.1-0.20251208185023-2f8c7e763cf8 // indirect github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 // indirect github.com/ulikunitz/xz v0.5.15 // indirect + github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.opentelemetry.io/contrib/detectors/gcp v1.39.0 // indirect @@ -132,5 +147,6 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 // indirect google.golang.org/grpc v1.79.3 // indirect google.golang.org/protobuf v1.36.11 // indirect + gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 2abce36f3b..5e18bdb488 100644 --- a/go.sum +++ b/go.sum @@ -26,6 +26,8 @@ cloud.google.com/go/storage v1.61.3 h1:VS//ZfBuPGDvakfD9xyPW1RGF1Vy3BWUoVZXgW1KM cloud.google.com/go/storage v1.61.3/go.mod h1:JtqK8BBB7TWv0HVGHubtUdzYYrakOQIsMLffZ2Z/HWk= cloud.google.com/go/trace v1.11.7 h1:kDNDX8JkaAG3R2nq1lIdkb7FCSi1rCmsEtKVsty7p+U= cloud.google.com/go/trace v1.11.7/go.mod h1:TNn9d5V3fQVf6s4SCveVMIBS2LJUqo73GACmq/Tky0s= +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0 h1:sBEjpZlNHzK1voKq9695PJSX2o5NEXl7/OL3coiIY0c= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0/go.mod h1:P4WPRUkOhJC13W//jWpyfJNDAIpvRbAUIYLX/4jtlE0= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.55.0 h1:UnDZ/zFfG1JhH/DqxIZYU/1CUAlTUScoXD/LcM2Ykk8= @@ -38,6 +40,11 @@ github.com/Ladicle/tabwriter v1.0.0 h1:DZQqPvMumBDwVNElso13afjYLNp0Z7pHqHnu0r4t9 github.com/Ladicle/tabwriter v1.0.0/go.mod h1:c4MdCjxQyTbGuQO/gvqJ+IA/89UEwrsD6hUCW98dyp4= github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/ProtonMail/go-crypto v1.1.6 h1:ZcV+Ropw6Qn0AX9brlQLAUXfqLBc7Bl+f/DmNxpLfdw= +github.com/ProtonMail/go-crypto v1.1.6/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= github.com/alecthomas/chroma/v2 v2.23.1 h1:nv2AVZdTyClGbVQkIzlDm/rnhk1E9bU9nXwmZ/Vk/iY= @@ -110,10 +117,14 @@ github.com/clipperhouse/displaywidth v0.11.0 h1:lBc6kY44VFw+TDx4I8opi/EtL9m20WSE github.com/clipperhouse/displaywidth v0.11.0/go.mod h1:bkrFNkf81G8HyVqmKGxsPufD3JhNl3dSqnGhOoSD/o0= github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJv2v7Vk= github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM= +github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8= +github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4= github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 h1:6xNmx7iTtyBRev0+D/Tv1FZd4SCg8axKApyNyRsAt/w= github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5/go.mod h1:KdCmV+x/BuvyMxRnYBlmVaq4OLiKW6iRQfvC62cvdkI= github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= +github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s= +github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -126,6 +137,8 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/elliotchance/orderedmap/v3 v3.1.0 h1:j4DJ5ObEmMBt/lcwIecKcoRxIQUEnw0L804lXYDt/pg= github.com/elliotchance/orderedmap/v3 v3.1.0/go.mod h1:G+Hc2RwaZvJMcS4JpGCOyViCnGeKf0bTYCGTO4uhjSo= +github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/envoyproxy/go-control-plane v0.14.0 h1:hbG2kr4RuFj222B6+7T83thSPqLjwBIfQawTkC++2HA= github.com/envoyproxy/go-control-plane v0.14.0/go.mod h1:NcS5X47pLl/hfqxU70yPwL9ZMkUlwlKxtAohpi2wBEU= github.com/envoyproxy/go-control-plane/envoy v1.36.0 h1:yg/JjO5E7ubRyKX3m07GF3reDNEnfOboJ0QySbH736g= @@ -140,6 +153,12 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +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.8.0 h1:I8hjc3LbBlXTtVuFNJuwYuMiHvQJDq1AT6u4DwDzZG0= +github.com/go-git/go-billy/v5 v5.8.0/go.mod h1:RpvI/rw4Vr5QA+Z60c6d6LXH0rYJo0uD5SqfmrrheCY= +github.com/go-git/go-git/v5 v5.17.2 h1:B+nkdlxdYrvyFK4GPXVU8w1U+YkbsgciIR7f2sZJ104= +github.com/go-git/go-git/v5 v5.17.2/go.mod h1:pW/VmeqkanRFqR6AljLcs7EA7FbZaN5MQqO7oZADXpo= github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -153,6 +172,8 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-task/template v0.2.0 h1:xW7ek0o65FUSTbKcSNeg2Vyf/I7wYXFgLUznptvviBE= github.com/go-task/template v0.2.0/go.mod h1:dbdoUb6qKnHQi1y6o+IdIrs0J4o/SEhSTA6bbzZmdtc= +github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= +github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= @@ -177,6 +198,8 @@ github.com/hashicorp/go-version v1.8.0 h1:KAkNb1HAiZd1ukkxDFGmokVZe1Xy9HG6NUp+bP github.com/hashicorp/go-version v1.8.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= 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/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE= @@ -208,7 +231,10 @@ github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELU github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU= github.com/pierrec/lz4/v4 v4.1.22/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4= +github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -227,6 +253,9 @@ github.com/sebdah/goldie/v2 v2.8.0/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvK github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= 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/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8= +github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY= github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spiffe/go-spiffe/v2 v2.6.0 h1:l+DolpxNWYgruGQVV0xsfeya3CsC7m8iBzDnMpsbLuo= @@ -234,6 +263,7 @@ github.com/spiffe/go-spiffe/v2 v2.6.0/go.mod h1:gm2SeUoMZEtpnzPNs2Csc0D/gX33k1xI github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= @@ -244,6 +274,8 @@ github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 h1:pyC9PaHYZFgEKFdlp3G8 github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701/go.mod h1:P3a5rG4X7tI17Nn3aOIAYr5HbIMukwXG0urG0WuL8OA= github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY= github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +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/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ= @@ -282,6 +314,12 @@ golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= @@ -295,6 +333,7 @@ golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8= golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA= golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= google.golang.org/api v0.271.0 h1:cIPN4qcUc61jlh7oXu6pwOQqbJW2GqYh5PS6rB2C/JY= @@ -313,6 +352,8 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/internal/fingerprint/gitignore.go b/internal/fingerprint/gitignore.go new file mode 100644 index 0000000000..0b9ad2053d --- /dev/null +++ b/internal/fingerprint/gitignore.go @@ -0,0 +1,60 @@ +package fingerprint + +import ( + "path/filepath" + "strings" + + "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/plumbing/format/gitignore" +) + +// filterGitignored removes entries from the file map that match gitignore rules. +// Files are expected to be absolute paths. The dir parameter is used to find the git repository. +// Returns the input map unchanged if the directory is not inside a git repository. +func filterGitignored(files map[string]bool, dir string) map[string]bool { + repo, err := git.PlainOpenWithOptions(dir, &git.PlainOpenOptions{ + DetectDotGit: true, + }) + if err != nil { + return files + } + + wt, err := repo.Worktree() + if err != nil { + return files + } + + var allPatterns []gitignore.Pattern + + if ps, err := gitignore.LoadSystemPatterns(wt.Filesystem); err == nil { + allPatterns = append(allPatterns, ps...) + } + + if ps, err := gitignore.LoadGlobalPatterns(wt.Filesystem); err == nil { + allPatterns = append(allPatterns, ps...) + } + + if ps, err := gitignore.ReadPatterns(wt.Filesystem, nil); err == nil { + allPatterns = append(allPatterns, ps...) + } + + if len(allPatterns) == 0 { + return files + } + + matcher := gitignore.NewMatcher(allPatterns) + gitRoot := wt.Filesystem.Root() + + for path := range files { + relPath, err := filepath.Rel(gitRoot, path) + if err != nil { + continue + } + pathComponents := strings.Split(filepath.ToSlash(relPath), "/") + if matcher.Match(pathComponents, false) { + files[path] = false + } + } + + return files +} diff --git a/internal/fingerprint/gitignore_test.go b/internal/fingerprint/gitignore_test.go new file mode 100644 index 0000000000..8eb0dbfdbb --- /dev/null +++ b/internal/fingerprint/gitignore_test.go @@ -0,0 +1,127 @@ +package fingerprint + +import ( + "os" + "path/filepath" + "testing" + + "github.com/go-git/go-git/v5" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/go-task/task/v3/taskfile/ast" +) + +func initGitRepo(t *testing.T, dir string) { + t.Helper() + _, err := git.PlainInit(dir, false) + require.NoError(t, err) +} + +func TestGlobsWithGitignore(t *testing.T) { + t.Parallel() + + dir, err := os.MkdirTemp("", "task-gitignore-test-*") + require.NoError(t, err) + t.Cleanup(func() { os.RemoveAll(dir) }) + + initGitRepo(t, dir) + + // Create test files + require.NoError(t, os.WriteFile(filepath.Join(dir, "included.txt"), []byte("included"), 0o644)) + require.NoError(t, os.WriteFile(filepath.Join(dir, "ignored.log"), []byte("ignored"), 0o644)) + require.NoError(t, os.WriteFile(filepath.Join(dir, "also-included.txt"), []byte("also included"), 0o644)) + + // Create .gitignore + require.NoError(t, os.WriteFile(filepath.Join(dir, ".gitignore"), []byte("*.log\n"), 0o644)) + + globs := []*ast.Glob{ + {Glob: "./*"}, + } + + // Without gitignore - should include all files + filesWithout, err := Globs(dir, globs, false) + require.NoError(t, err) + + // With gitignore - should exclude .log files + filesWith, err := Globs(dir, globs, true) + require.NoError(t, err) + + // The .log file should be in the unfiltered list + hasLog := false + for _, f := range filesWithout { + if filepath.Base(f) == "ignored.log" { + hasLog = true + break + } + } + assert.True(t, hasLog, "ignored.log should be present without gitignore filter") + + // The .log file should NOT be in the filtered list + hasLog = false + for _, f := range filesWith { + if filepath.Base(f) == "ignored.log" { + hasLog = true + break + } + } + assert.False(t, hasLog, "ignored.log should be excluded with gitignore filter") + + // .txt files should still be present + txtCount := 0 + for _, f := range filesWith { + if filepath.Ext(f) == ".txt" { + txtCount++ + } + } + assert.Equal(t, 2, txtCount, "both .txt files should remain") +} + +func TestGlobsWithGitignoreDisabled(t *testing.T) { + t.Parallel() + + dir, err := os.MkdirTemp("", "task-gitignore-disabled-*") + require.NoError(t, err) + t.Cleanup(func() { os.RemoveAll(dir) }) + + initGitRepo(t, dir) + require.NoError(t, os.WriteFile(filepath.Join(dir, "file.txt"), []byte("content"), 0o644)) + require.NoError(t, os.WriteFile(filepath.Join(dir, "file.log"), []byte("content"), 0o644)) + require.NoError(t, os.WriteFile(filepath.Join(dir, ".gitignore"), []byte("*.log\n"), 0o644)) + + globs := []*ast.Glob{ + {Glob: "./*"}, + } + + // WithGitignore(false, ...) should not filter + files, err := Globs(dir, globs, false) + require.NoError(t, err) + + hasLog := false + for _, f := range files { + if filepath.Base(f) == "file.log" { + hasLog = true + break + } + } + assert.True(t, hasLog, "file.log should be present when gitignore is disabled") +} + +func TestGlobsWithGitignoreNoRepo(t *testing.T) { + t.Parallel() + + dir, err := os.MkdirTemp("", "task-gitignore-norepo-*") + require.NoError(t, err) + t.Cleanup(func() { os.RemoveAll(dir) }) + + require.NoError(t, os.WriteFile(filepath.Join(dir, "file.txt"), []byte("content"), 0o644)) + + globs := []*ast.Glob{ + {Glob: "./*"}, + } + + // Should not error and should return all files + files, err := Globs(dir, globs, true) + require.NoError(t, err) + assert.Len(t, files, 1) +} diff --git a/internal/fingerprint/glob.go b/internal/fingerprint/glob.go index fd3cafceaa..c87c9ec3b5 100644 --- a/internal/fingerprint/glob.go +++ b/internal/fingerprint/glob.go @@ -10,7 +10,7 @@ import ( "github.com/go-task/task/v3/taskfile/ast" ) -func Globs(dir string, globs []*ast.Glob) ([]string, error) { +func Globs(dir string, globs []*ast.Glob, gitignore bool) ([]string, error) { resultMap := make(map[string]bool) for _, g := range globs { matches, err := glob(dir, g.Glob) @@ -21,6 +21,11 @@ func Globs(dir string, globs []*ast.Glob) ([]string, error) { resultMap[match] = !g.Negate } } + + if gitignore { + resultMap = filterGitignored(resultMap, dir) + } + return collectKeys(resultMap), nil } diff --git a/internal/fingerprint/sources_checksum.go b/internal/fingerprint/sources_checksum.go index f1108e111c..ef9e7387b3 100644 --- a/internal/fingerprint/sources_checksum.go +++ b/internal/fingerprint/sources_checksum.go @@ -89,7 +89,7 @@ func (*ChecksumChecker) Kind() string { } func (c *ChecksumChecker) checksum(t *ast.Task) (string, error) { - sources, err := Globs(t.Dir, t.Sources) + sources, err := Globs(t.Dir, t.Sources, t.IsGitignore()) if err != nil { return "", err } diff --git a/internal/fingerprint/sources_timestamp.go b/internal/fingerprint/sources_timestamp.go index 258d9386d9..5d48285193 100644 --- a/internal/fingerprint/sources_timestamp.go +++ b/internal/fingerprint/sources_timestamp.go @@ -28,7 +28,7 @@ func (checker *TimestampChecker) IsUpToDate(t *ast.Task) (bool, error) { return false, nil } - sources, err := Globs(t.Dir, t.Sources) + sources, err := Globs(t.Dir, t.Sources, t.IsGitignore()) if err != nil { return false, nil } @@ -54,7 +54,7 @@ func (checker *TimestampChecker) IsUpToDate(t *ast.Task) (bool, error) { } } - generates, err := Globs(t.Dir, t.Generates) + generates, err := Globs(t.Dir, t.Generates, t.IsGitignore()) if err != nil { return false, nil } @@ -112,7 +112,7 @@ func (checker *TimestampChecker) Kind() string { // Value implements the Checker Interface func (checker *TimestampChecker) Value(t *ast.Task) (any, error) { - sources, err := Globs(t.Dir, t.Sources) + sources, err := Globs(t.Dir, t.Sources, t.IsGitignore()) if err != nil { return time.Now(), err } diff --git a/task_test.go b/task_test.go index 80915c2c47..784c03257c 100644 --- a/task_test.go +++ b/task_test.go @@ -653,6 +653,55 @@ func TestStatusChecksumMissingGenerated(t *testing.T) { // nolint:paralleltest / require.NoError(t, err, "generated.txt should be recreated after third run") } +func TestGitignoreChecksum(t *testing.T) { //nolint:paralleltest // cannot run in parallel + const dir = "testdata/gitignore" + + // Clean up + _ = os.RemoveAll(filepathext.SmartJoin(dir, ".task")) + _ = os.Remove(filepathext.SmartJoin(dir, "generated.txt")) + + var buff bytes.Buffer + tempDir := task.TempDir{ + Remote: filepathext.SmartJoin(dir, ".task"), + Fingerprint: filepathext.SmartJoin(dir, ".task"), + } + e := task.NewExecutor( + task.WithDir(dir), + task.WithStdout(&buff), + task.WithStderr(&buff), + task.WithTempDir(tempDir), + ) + require.NoError(t, e.Setup()) + + // First run - should execute + require.NoError(t, e.Run(t.Context(), &task.Call{Task: "build"})) + + // Second run - should be up to date + buff.Reset() + require.NoError(t, e.Run(t.Context(), &task.Call{Task: "build"})) + assert.Equal(t, "task: Task \"build\" is up to date\n", buff.String()) + + // Modify the ignored file - should still be up to date + require.NoError(t, os.WriteFile(filepathext.SmartJoin(dir, "ignored.txt"), []byte("modified\n"), 0o644)) + buff.Reset() + require.NoError(t, e.Run(t.Context(), &task.Call{Task: "build"})) + assert.Equal(t, "task: Task \"build\" is up to date\n", buff.String()) + + // Modify the source file - should re-execute + require.NoError(t, os.WriteFile(filepathext.SmartJoin(dir, "source.txt"), []byte("modified source\n"), 0o644)) + buff.Reset() + require.NoError(t, e.Run(t.Context(), &task.Call{Task: "build"})) + assert.NotEqual(t, "task: Task \"build\" is up to date\n", buff.String()) + + // Restore source file + require.NoError(t, os.WriteFile(filepathext.SmartJoin(dir, "source.txt"), []byte("source content\n"), 0o644)) + require.NoError(t, os.WriteFile(filepathext.SmartJoin(dir, "ignored.txt"), []byte("ignored content\n"), 0o644)) + + // Clean up + _ = os.RemoveAll(filepathext.SmartJoin(dir, ".task")) + _ = os.Remove(filepathext.SmartJoin(dir, "generated.txt")) +} + func TestStatusVariables(t *testing.T) { t.Parallel() diff --git a/taskfile/ast/task.go b/taskfile/ast/task.go index 0e9893943e..30212ab613 100644 --- a/taskfile/ast/task.go +++ b/taskfile/ast/task.go @@ -38,6 +38,7 @@ type Task struct { Method string Prefix string `hash:"ignore"` IgnoreError bool + Gitignore *bool Run string Platforms []*Platform If string @@ -75,6 +76,12 @@ func (t *Task) IsSilent() bool { return t.Silent != nil && *t.Silent } +// IsGitignore returns true if the task has gitignore filtering explicitly enabled. +// Returns false if Gitignore is nil (not set) or explicitly set to false. +func (t *Task) IsGitignore() bool { + return t.Gitignore != nil && *t.Gitignore +} + // WildcardMatch will check if the given string matches the name of the Task and returns any wildcard values. func (t *Task) WildcardMatch(name string) (bool, []string) { names := append([]string{t.Task}, t.Aliases...) @@ -150,6 +157,7 @@ func (t *Task) UnmarshalYAML(node *yaml.Node) error { Method string Prefix string IgnoreError bool `yaml:"ignore_error"` + Gitignore *bool `yaml:"gitignore,omitempty"` Run string Platforms []*Platform If string @@ -190,6 +198,7 @@ func (t *Task) UnmarshalYAML(node *yaml.Node) error { t.Method = task.Method t.Prefix = task.Prefix t.IgnoreError = task.IgnoreError + t.Gitignore = deepcopy.Scalar(task.Gitignore) t.Run = task.Run t.Platforms = task.Platforms t.If = task.If @@ -233,6 +242,7 @@ func (t *Task) DeepCopy() *Task { Method: t.Method, Prefix: t.Prefix, IgnoreError: t.IgnoreError, + Gitignore: deepcopy.Scalar(t.Gitignore), Run: t.Run, IncludeVars: t.IncludeVars.DeepCopy(), IncludedTaskfileVars: t.IncludedTaskfileVars.DeepCopy(), diff --git a/taskfile/ast/taskfile.go b/taskfile/ast/taskfile.go index 4e3a3e4255..9216f39660 100644 --- a/taskfile/ast/taskfile.go +++ b/taskfile/ast/taskfile.go @@ -30,10 +30,11 @@ type Taskfile struct { Vars *Vars Env *Vars Tasks *Tasks - Silent bool - Dotenv []string - Run string - Interval time.Duration + Silent bool + Dotenv []string + Run string + Interval time.Duration + Gitignore bool } // Merge merges the second Taskfile into the first @@ -88,7 +89,8 @@ func (tf *Taskfile) UnmarshalYAML(node *yaml.Node) error { Silent bool Dotenv []string Run string - Interval time.Duration + Interval time.Duration + Gitignore bool } if err := node.Decode(&taskfile); err != nil { return errors.NewTaskfileDecodeError(err, node) @@ -106,6 +108,7 @@ func (tf *Taskfile) UnmarshalYAML(node *yaml.Node) error { tf.Dotenv = taskfile.Dotenv tf.Run = taskfile.Run tf.Interval = taskfile.Interval + tf.Gitignore = taskfile.Gitignore if tf.Includes == nil { tf.Includes = NewIncludes() } diff --git a/testdata/gitignore/.gitignore b/testdata/gitignore/.gitignore new file mode 100644 index 0000000000..f89d64dab6 --- /dev/null +++ b/testdata/gitignore/.gitignore @@ -0,0 +1 @@ +ignored.txt diff --git a/testdata/gitignore/Taskfile.yml b/testdata/gitignore/Taskfile.yml new file mode 100644 index 0000000000..c78e5a0efb --- /dev/null +++ b/testdata/gitignore/Taskfile.yml @@ -0,0 +1,25 @@ +version: '3' + +gitignore: true + +tasks: + build: + cmds: + - cp ./source.txt ./generated.txt + sources: + - ./*.txt + - exclude: ./generated.txt + generates: + - ./generated.txt + method: checksum + + build-no-gitignore: + gitignore: false + cmds: + - cp ./source.txt ./generated.txt + sources: + - ./*.txt + - exclude: ./generated.txt + generates: + - ./generated.txt + method: checksum diff --git a/testdata/gitignore/source.txt b/testdata/gitignore/source.txt new file mode 100644 index 0000000000..48763f0349 --- /dev/null +++ b/testdata/gitignore/source.txt @@ -0,0 +1 @@ +source content diff --git a/variables.go b/variables.go index c7c6cc8493..18d716a548 100644 --- a/variables.go +++ b/variables.go @@ -59,6 +59,7 @@ func (e *Executor) CompiledTaskForTaskList(call *Call) (*ast.Task, error) { Env: nil, Dotenv: origTask.Dotenv, Silent: deepcopy.Scalar(origTask.Silent), + Gitignore: deepcopy.Scalar(origTask.Gitignore), Interactive: origTask.Interactive, Internal: origTask.Internal, Method: origTask.Method, @@ -110,6 +111,11 @@ func (e *Executor) compiledTask(call *Call, evaluateShVars bool) (*ast.Task, err } } + gitignore := origTask.IsGitignore() + if origTask.Gitignore == nil { + gitignore = e.Taskfile.Gitignore + } + new := ast.Task{ Task: origTask.Task, Label: templater.Replace(origTask.Label, cache), @@ -126,6 +132,7 @@ func (e *Executor) compiledTask(call *Call, evaluateShVars bool) (*ast.Task, err Env: nil, Dotenv: templater.Replace(origTask.Dotenv, cache), Silent: deepcopy.Scalar(origTask.Silent), + Gitignore: &gitignore, Interactive: origTask.Interactive, Internal: origTask.Internal, Method: templater.Replace(origTask.Method, cache), @@ -219,7 +226,7 @@ func (e *Executor) compiledTask(call *Call, evaluateShVars bool) (*ast.Task, err continue } if cmd.For != nil { - list, keys, err := itemsFromFor(cmd.For, new.Dir, new.Sources, new.Generates, vars, origTask.Location, cache) + list, keys, err := itemsFromFor(cmd.For, new.Dir, new.Sources, new.Generates, gitignore, vars, origTask.Location, cache) if err != nil { return nil, err } @@ -268,7 +275,7 @@ func (e *Executor) compiledTask(call *Call, evaluateShVars bool) (*ast.Task, err continue } if dep.For != nil { - list, keys, err := itemsFromFor(dep.For, new.Dir, new.Sources, new.Generates, vars, origTask.Location, cache) + list, keys, err := itemsFromFor(dep.For, new.Dir, new.Sources, new.Generates, gitignore, vars, origTask.Location, cache) if err != nil { return nil, err } @@ -339,6 +346,7 @@ func itemsFromFor( dir string, sources []*ast.Glob, generates []*ast.Glob, + gitignore bool, vars *ast.Vars, location *ast.Location, cache *templater.Cache, @@ -361,7 +369,7 @@ func itemsFromFor( } // Get the list from the task sources if f.From == "sources" { - glist, err := fingerprint.Globs(dir, sources) + glist, err := fingerprint.Globs(dir, sources, gitignore) if err != nil { return nil, nil, err } @@ -375,7 +383,7 @@ func itemsFromFor( } // Get the list from the task generates if f.From == "generates" { - glist, err := fingerprint.Globs(dir, generates) + glist, err := fingerprint.Globs(dir, generates, gitignore) if err != nil { return nil, nil, err } diff --git a/watch.go b/watch.go index 8e7f7ccf7d..349dd57a69 100644 --- a/watch.go +++ b/watch.go @@ -205,7 +205,7 @@ func (e *Executor) collectSources(calls []*Call) ([]string, error) { var sources []string err := e.traverse(calls, func(task *ast.Task) error { - files, err := fingerprint.Globs(task.Dir, task.Sources) + files, err := fingerprint.Globs(task.Dir, task.Sources, task.IsGitignore()) if err != nil { return err } diff --git a/website/src/public/schema.json b/website/src/public/schema.json index 2210952d62..37751fa4fe 100644 --- a/website/src/public/schema.json +++ b/website/src/public/schema.json @@ -177,6 +177,11 @@ "enum": ["none", "checksum", "timestamp"], "default": "none" }, + "gitignore": { + "description": "When set to true, files matching .gitignore rules will be excluded from sources and generates glob resolution. Overrides the global gitignore setting.", + "type": "boolean", + "default": false + }, "prefix": { "description": "Defines a string to prefix the output of tasks running in parallel. Only used when the output mode is `prefixed`.", "type": "string" @@ -687,6 +692,11 @@ "enum": ["none", "checksum", "timestamp"], "default": "checksum" }, + "gitignore": { + "description": "When set to true, files matching .gitignore rules will be excluded from sources and generates glob resolution for all tasks. Can be overridden per task.", + "type": "boolean", + "default": false + }, "includes": { "description": "Imports tasks from the specified taskfiles. The tasks described in the given Taskfiles will be available with the informed namespace.", "type": "object", From 714ffdb1b5aae84925792acc9e847db459cd25df Mon Sep 17 00:00:00 2001 From: Valentin Maerten Date: Fri, 3 Apr 2026 22:54:41 +0200 Subject: [PATCH 2/6] refactor: replace go-git with sabhiram/go-gitignore for lighter dependency go-git pulled ~30 transitive dependencies and recursively walked the entire worktree on every Globs() call. Replace with sabhiram/go-gitignore (zero dependencies) and a simple walk from task dir up to rootDir to collect .gitignore files. Pass rootDir (Taskfile ROOT_DIR) through the checker chain to bound the search scope. --- go.mod | 93 +++++----- go.sum | 197 +++++++++------------- internal/fingerprint/gitignore.go | 94 +++++++---- internal/fingerprint/gitignore_test.go | 45 ++--- internal/fingerprint/glob.go | 4 +- internal/fingerprint/sources.go | 6 +- internal/fingerprint/sources_checksum.go | 6 +- internal/fingerprint/sources_timestamp.go | 10 +- internal/fingerprint/task.go | 9 +- status.go | 2 +- task.go | 1 + variables.go | 13 +- watch.go | 2 +- 13 files changed, 227 insertions(+), 255 deletions(-) diff --git a/go.mod b/go.mod index 181964d89e..a9316af924 100644 --- a/go.mod +++ b/go.mod @@ -18,10 +18,11 @@ require ( github.com/go-task/slim-sprig/v3 v3.0.0 github.com/go-task/template v0.2.0 github.com/google/uuid v1.6.0 - github.com/hashicorp/go-getter v1.8.6 + github.com/hashicorp/go-getter v1.8.5 github.com/joho/godotenv v1.5.1 github.com/mitchellh/hashstructure/v2 v2.0.2 github.com/puzpuzpuz/xsync/v4 v4.4.0 + github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 github.com/sajari/fuzzy v1.0.0 github.com/sebdah/goldie/v2 v2.8.0 github.com/spf13/pflag v1.0.10 @@ -29,46 +30,43 @@ require ( github.com/zeebo/xxh3 v1.1.0 go.yaml.in/yaml/v3 v3.0.4 golang.org/x/sync v0.20.0 - golang.org/x/term v0.42.0 + golang.org/x/term v0.41.0 mvdan.cc/sh/moreinterp v0.0.0-20260120230322-19def062a997 - mvdan.cc/sh/v3 v3.13.1 + mvdan.cc/sh/v3 v3.13.0 ) require ( cel.dev/expr v0.25.1 // indirect cloud.google.com/go v0.123.0 // indirect - cloud.google.com/go/auth v0.18.2 // indirect + cloud.google.com/go/auth v0.18.1 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect cloud.google.com/go/compute/metadata v0.9.0 // indirect cloud.google.com/go/iam v1.5.3 // indirect cloud.google.com/go/monitoring v1.24.3 // indirect - cloud.google.com/go/storage v1.61.3 // indirect - dario.cat/mergo v1.0.0 // indirect + cloud.google.com/go/storage v1.60.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.55.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.55.0 // indirect - github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/ProtonMail/go-crypto v1.1.6 // indirect github.com/atotto/clipboard v0.1.4 // indirect - github.com/aws/aws-sdk-go-v2 v1.41.5 // indirect - github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8 // indirect - github.com/aws/aws-sdk-go-v2/config v1.32.12 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.19.12 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.20 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21 // indirect - github.com/aws/aws-sdk-go-v2/service/s3 v1.97.3 // indirect - github.com/aws/aws-sdk-go-v2/service/signin v1.0.8 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.30.13 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.17 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.41.9 // indirect - github.com/aws/smithy-go v1.24.2 // indirect + github.com/aws/aws-sdk-go-v2 v1.41.1 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.4 // indirect + github.com/aws/aws-sdk-go-v2/config v1.32.9 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.19.9 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.17 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.17 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.17 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.8 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.17 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.17 // indirect + github.com/aws/aws-sdk-go-v2/service/s3 v1.96.0 // indirect + github.com/aws/aws-sdk-go-v2/service/signin v1.0.5 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.30.10 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.14 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.41.6 // indirect + github.com/aws/smithy-go v1.24.0 // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/charmbracelet/colorprofile v0.4.2 // indirect @@ -79,31 +77,22 @@ require ( github.com/charmbracelet/x/windows v0.2.2 // indirect github.com/clipperhouse/displaywidth v0.11.0 // indirect github.com/clipperhouse/uax29/v2 v2.7.0 // indirect - github.com/cloudflare/circl v1.6.3 // indirect github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 // indirect - github.com/cyphar/filepath-securejoin v0.4.1 // indirect github.com/dlclark/regexp2 v1.11.5 // indirect github.com/dustin/go-humanize v1.0.1 // indirect - github.com/emirpasic/gods v1.18.1 // indirect github.com/envoyproxy/go-control-plane/envoy v1.36.0 // indirect github.com/envoyproxy/protoc-gen-validate v1.3.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect - github.com/go-git/go-billy/v5 v5.8.0 // indirect - github.com/go-git/go-git/v5 v5.17.2 // indirect github.com/go-jose/go-jose/v4 v4.1.4 // indirect github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect github.com/google/s2a-go v0.1.9 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.3.14 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.11 // indirect github.com/googleapis/gax-go/v2 v2.17.0 // indirect - github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.72 // indirect + github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.70 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-version v1.8.0 // indirect - github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/kevinburke/ssh_config v1.2.0 // indirect - github.com/klauspost/compress v1.18.5 // indirect + github.com/klauspost/compress v1.18.4 // indirect github.com/klauspost/cpuid/v2 v2.2.10 // indirect github.com/klauspost/pgzip v1.2.6 // indirect github.com/lucasb-eyer/go-colorful v1.3.0 // indirect @@ -113,40 +102,36 @@ require ( github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/muesli/cancelreader v0.2.2 // indirect github.com/pierrec/lz4/v4 v4.1.22 // indirect - github.com/pjbgf/sha1cd v0.3.2 // indirect github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect - github.com/skeema/knownhosts v1.3.1 // indirect github.com/spiffe/go-spiffe/v2 v2.6.0 // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/u-root/u-root v0.15.1-0.20251208185023-2f8c7e763cf8 // indirect github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 // indirect github.com/ulikunitz/xz v0.5.15 // indirect - github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.opentelemetry.io/contrib/detectors/gcp v1.39.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect - go.opentelemetry.io/otel v1.43.0 // indirect - go.opentelemetry.io/otel/metric v1.43.0 // indirect - go.opentelemetry.io/otel/sdk v1.43.0 // indirect - go.opentelemetry.io/otel/sdk/metric v1.43.0 // indirect - go.opentelemetry.io/otel/trace v1.43.0 // indirect - golang.org/x/crypto v0.49.0 // indirect - golang.org/x/net v0.52.0 // indirect + go.opentelemetry.io/otel v1.40.0 // indirect + go.opentelemetry.io/otel/metric v1.40.0 // indirect + go.opentelemetry.io/otel/sdk v1.40.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.40.0 // indirect + go.opentelemetry.io/otel/trace v1.40.0 // indirect + golang.org/x/crypto v0.48.0 // indirect + golang.org/x/net v0.51.0 // indirect golang.org/x/oauth2 v0.36.0 // indirect - golang.org/x/sys v0.43.0 // indirect - golang.org/x/text v0.35.0 // indirect + golang.org/x/sys v0.42.0 // indirect + golang.org/x/text v0.34.0 // indirect golang.org/x/time v0.15.0 // indirect - google.golang.org/api v0.271.0 // indirect + google.golang.org/api v0.267.0 // indirect google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20260203192932-546029d2fa20 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260203192932-546029d2fa20 // indirect google.golang.org/grpc v1.79.3 // indirect google.golang.org/protobuf v1.36.11 // indirect - gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 5e18bdb488..e231960abb 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,8 @@ charm.land/lipgloss/v2 v2.0.2 h1:xFolbF8JdpNkM2cEPTfXEcW1p6NRzOWTSamRfYEw8cs= charm.land/lipgloss/v2 v2.0.2/go.mod h1:KjPle2Qd3YmvP1KL5OMHiHysGcNwq6u83MUjYkFvEkM= cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE= cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU= -cloud.google.com/go/auth v0.18.2 h1:+Nbt5Ev0xEqxlNjd6c+yYUeosQ5TtEUaNcN/3FozlaM= -cloud.google.com/go/auth v0.18.2/go.mod h1:xD+oY7gcahcu7G2SG2DsBerfFxgPAJz17zz2joOFF3M= +cloud.google.com/go/auth v0.18.1 h1:IwTEx92GFUo2pJ6Qea0EU3zYvKnTAeRCODxfA/G5UWs= +cloud.google.com/go/auth v0.18.1/go.mod h1:GfTYoS9G3CWpRA3Va9doKN9mjPGRS+v41jmZAhBzbrA= cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc= cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= @@ -22,12 +22,10 @@ cloud.google.com/go/longrunning v0.8.0 h1:LiKK77J3bx5gDLi4SMViHixjD2ohlkwBi+mKA7 cloud.google.com/go/longrunning v0.8.0/go.mod h1:UmErU2Onzi+fKDg2gR7dusz11Pe26aknR4kHmJJqIfk= cloud.google.com/go/monitoring v1.24.3 h1:dde+gMNc0UhPZD1Azu6at2e79bfdztVDS5lvhOdsgaE= cloud.google.com/go/monitoring v1.24.3/go.mod h1:nYP6W0tm3N9H/bOw8am7t62YTzZY+zUeQ+Bi6+2eonI= -cloud.google.com/go/storage v1.61.3 h1:VS//ZfBuPGDvakfD9xyPW1RGF1Vy3BWUoVZXgW1KMOg= -cloud.google.com/go/storage v1.61.3/go.mod h1:JtqK8BBB7TWv0HVGHubtUdzYYrakOQIsMLffZ2Z/HWk= +cloud.google.com/go/storage v1.60.0 h1:oBfZrSOCimggVNz9Y/bXY35uUcts7OViubeddTTVzQ8= +cloud.google.com/go/storage v1.60.0/go.mod h1:q+5196hXfejkctrnx+VYU8RKQr/L3c0cBIlrjmiAKE0= cloud.google.com/go/trace v1.11.7 h1:kDNDX8JkaAG3R2nq1lIdkb7FCSi1rCmsEtKVsty7p+U= cloud.google.com/go/trace v1.11.7/go.mod h1:TNn9d5V3fQVf6s4SCveVMIBS2LJUqo73GACmq/Tky0s= -dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= -dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0 h1:sBEjpZlNHzK1voKq9695PJSX2o5NEXl7/OL3coiIY0c= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0/go.mod h1:P4WPRUkOhJC13W//jWpyfJNDAIpvRbAUIYLX/4jtlE0= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.55.0 h1:UnDZ/zFfG1JhH/DqxIZYU/1CUAlTUScoXD/LcM2Ykk8= @@ -40,11 +38,6 @@ github.com/Ladicle/tabwriter v1.0.0 h1:DZQqPvMumBDwVNElso13afjYLNp0Z7pHqHnu0r4t9 github.com/Ladicle/tabwriter v1.0.0/go.mod h1:c4MdCjxQyTbGuQO/gvqJ+IA/89UEwrsD6hUCW98dyp4= github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= -github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= -github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/ProtonMail/go-crypto v1.1.6 h1:ZcV+Ropw6Qn0AX9brlQLAUXfqLBc7Bl+f/DmNxpLfdw= -github.com/ProtonMail/go-crypto v1.1.6/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= github.com/alecthomas/chroma/v2 v2.23.1 h1:nv2AVZdTyClGbVQkIzlDm/rnhk1E9bU9nXwmZ/Vk/iY= @@ -53,44 +46,44 @@ github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= -github.com/aws/aws-sdk-go-v2 v1.41.5 h1:dj5kopbwUsVUVFgO4Fi5BIT3t4WyqIDjGKCangnV/yY= -github.com/aws/aws-sdk-go-v2 v1.41.5/go.mod h1:mwsPRE8ceUUpiTgF7QmQIJ7lgsKUPQOUl3o72QBrE1o= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8 h1:eBMB84YGghSocM7PsjmmPffTa+1FBUeNvGvFou6V/4o= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8/go.mod h1:lyw7GFp3qENLh7kwzf7iMzAxDn+NzjXEAGjKS2UOKqI= -github.com/aws/aws-sdk-go-v2/config v1.32.12 h1:O3csC7HUGn2895eNrLytOJQdoL2xyJy0iYXhoZ1OmP0= -github.com/aws/aws-sdk-go-v2/config v1.32.12/go.mod h1:96zTvoOFR4FURjI+/5wY1vc1ABceROO4lWgWJuxgy0g= -github.com/aws/aws-sdk-go-v2/credentials v1.19.12 h1:oqtA6v+y5fZg//tcTWahyN9PEn5eDU/Wpvc2+kJ4aY8= -github.com/aws/aws-sdk-go-v2/credentials v1.19.12/go.mod h1:U3R1RtSHx6NB0DvEQFGyf/0sbrpJrluENHdPy1j/3TE= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.20 h1:zOgq3uezl5nznfoK3ODuqbhVg1JzAGDUhXOsU0IDCAo= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.20/go.mod h1:z/MVwUARehy6GAg/yQ1GO2IMl0k++cu1ohP9zo887wE= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21 h1:Rgg6wvjjtX8bNHcvi9OnXWwcE0a2vGpbwmtICOsvcf4= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21/go.mod h1:A/kJFst/nm//cyqonihbdpQZwiUhhzpqTsdbhDdRF9c= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21 h1:PEgGVtPoB6NTpPrBgqSE5hE/o47Ij9qk/SEZFbUOe9A= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21/go.mod h1:p+hz+PRAYlY3zcpJhPwXlLC4C+kqn70WIHwnzAfs6ps= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 h1:qYQ4pzQ2Oz6WpQ8T3HvGHnZydA72MnLuFK9tJwmrbHw= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6/go.mod h1:O3h0IK87yXci+kg6flUKzJnWeziQUKciKrLjcatSNcY= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22 h1:rWyie/PxDRIdhNf4DzRk0lvjVOqFJuNnO8WwaIRVxzQ= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22/go.mod h1:zd/JsJ4P7oGfUhXn1VyLqaRZwPmZwg44Jf2dS84Dm3Y= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 h1:5EniKhLZe4xzL7a+fU3C2tfUN4nWIqlLesfrjkuPFTY= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7/go.mod h1:x0nZssQ3qZSnIcePWLvcoFisRXJzcTVvYpAAdYX8+GI= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13 h1:JRaIgADQS/U6uXDqlPiefP32yXTda7Kqfx+LgspooZM= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13/go.mod h1:CEuVn5WqOMilYl+tbccq8+N2ieCy0gVn3OtRb0vBNNM= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21 h1:c31//R3xgIJMSC8S6hEVq+38DcvUlgFY0FM6mSI5oto= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21/go.mod h1:r6+pf23ouCB718FUxaqzZdbpYFyDtehyZcmP5KL9FkA= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21 h1:ZlvrNcHSFFWURB8avufQq9gFsheUgjVD9536obIknfM= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21/go.mod h1:cv3TNhVrssKR0O/xxLJVRfd2oazSnZnkUeTf6ctUwfQ= -github.com/aws/aws-sdk-go-v2/service/s3 v1.97.3 h1:HwxWTbTrIHm5qY+CAEur0s/figc3qwvLWsNkF4RPToo= -github.com/aws/aws-sdk-go-v2/service/s3 v1.97.3/go.mod h1:uoA43SdFwacedBfSgfFSjjCvYe8aYBS7EnU5GZ/YKMM= -github.com/aws/aws-sdk-go-v2/service/signin v1.0.8 h1:0GFOLzEbOyZABS3PhYfBIx2rNBACYcKty+XGkTgw1ow= -github.com/aws/aws-sdk-go-v2/service/signin v1.0.8/go.mod h1:LXypKvk85AROkKhOG6/YEcHFPoX+prKTowKnVdcaIxE= -github.com/aws/aws-sdk-go-v2/service/sso v1.30.13 h1:kiIDLZ005EcKomYYITtfsjn7dtOwHDOFy7IbPXKek2o= -github.com/aws/aws-sdk-go-v2/service/sso v1.30.13/go.mod h1:2h/xGEowcW/g38g06g3KpRWDlT+OTfxxI0o1KqayAB8= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.17 h1:jzKAXIlhZhJbnYwHbvUQZEB8KfgAEuG0dc08Bkda7NU= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.17/go.mod h1:Al9fFsXjv4KfbzQHGe6V4NZSZQXecFcvaIF4e70FoRA= -github.com/aws/aws-sdk-go-v2/service/sts v1.41.9 h1:Cng+OOwCHmFljXIxpEVXAGMnBia8MSU6Ch5i9PgBkcU= -github.com/aws/aws-sdk-go-v2/service/sts v1.41.9/go.mod h1:LrlIndBDdjA/EeXeyNBle+gyCwTlizzW5ycgWnvIxkk= -github.com/aws/smithy-go v1.24.2 h1:FzA3bu/nt/vDvmnkg+R8Xl46gmzEDam6mZ1hzmwXFng= -github.com/aws/smithy-go v1.24.2/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= +github.com/aws/aws-sdk-go-v2 v1.41.1 h1:ABlyEARCDLN034NhxlRUSZr4l71mh+T5KAeGh6cerhU= +github.com/aws/aws-sdk-go-v2 v1.41.1/go.mod h1:MayyLB8y+buD9hZqkCW3kX1AKq07Y5pXxtgB+rRFhz0= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.4 h1:489krEF9xIGkOaaX3CE/Be2uWjiXrkCH6gUX+bZA/BU= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.4/go.mod h1:IOAPF6oT9KCsceNTvvYMNHy0+kMF8akOjeDvPENWxp4= +github.com/aws/aws-sdk-go-v2/config v1.32.9 h1:ktda/mtAydeObvJXlHzyGpK1xcsLaP16zfUPDGoW90A= +github.com/aws/aws-sdk-go-v2/config v1.32.9/go.mod h1:U+fCQ+9QKsLW786BCfEjYRj34VVTbPdsLP3CHSYXMOI= +github.com/aws/aws-sdk-go-v2/credentials v1.19.9 h1:sWvTKsyrMlJGEuj/WgrwilpoJ6Xa1+KhIpGdzw7mMU8= +github.com/aws/aws-sdk-go-v2/credentials v1.19.9/go.mod h1:+J44MBhmfVY/lETFiKI+klz0Vym2aCmIjqgClMmW82w= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17 h1:I0GyV8wiYrP8XpA70g1HBcQO1JlQxCMTW9npl5UbDHY= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17/go.mod h1:tyw7BOl5bBe/oqvoIeECFJjMdzXoa/dfVz3QQ5lgHGA= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.17 h1:xOLELNKGp2vsiteLsvLPwxC+mYmO6OZ8PYgiuPJzF8U= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.17/go.mod h1:5M5CI3D12dNOtH3/mk6minaRwI2/37ifCURZISxA/IQ= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.17 h1:WWLqlh79iO48yLkj1v3ISRNiv+3KdQoZ6JWyfcsyQik= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.17/go.mod h1:EhG22vHRrvF8oXSTYStZhJc1aUgKtnJe+aOiFEV90cM= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 h1:WKuaxf++XKWlHWu9ECbMlha8WOEGm0OUEZqm4K/Gcfk= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4/go.mod h1:ZWy7j6v1vWGmPReu0iSGvRiise4YI5SkR3OHKTZ6Wuc= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.17 h1:JqcdRG//czea7Ppjb+g/n4o8i/R50aTBHkA7vu0lK+k= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.17/go.mod h1:CO+WeGmIdj/MlPel2KwID9Gt7CNq4M65HUfBW97liM0= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4 h1:0ryTNEdJbzUCEWkVXEXoqlXV72J5keC1GvILMOuD00E= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4/go.mod h1:HQ4qwNZh32C3CBeO6iJLQlgtMzqeG17ziAA/3KDJFow= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.8 h1:Z5EiPIzXKewUQK0QTMkutjiaPVeVYXX7KIqhXu/0fXs= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.8/go.mod h1:FsTpJtvC4U1fyDXk7c71XoDv3HlRm8V3NiYLeYLh5YE= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.17 h1:RuNSMoozM8oXlgLG/n6WLaFGoea7/CddrCfIiSA+xdY= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.17/go.mod h1:F2xxQ9TZz5gDWsclCtPQscGpP0VUOc8RqgFM3vDENmU= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.17 h1:bGeHBsGZx0Dvu/eJC0Lh9adJa3M1xREcndxLNZlve2U= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.17/go.mod h1:dcW24lbU0CzHusTE8LLHhRLI42ejmINN8Lcr22bwh/g= +github.com/aws/aws-sdk-go-v2/service/s3 v1.96.0 h1:oeu8VPlOre74lBA/PMhxa5vewaMIMmILM+RraSyB8KA= +github.com/aws/aws-sdk-go-v2/service/s3 v1.96.0/go.mod h1:5jggDlZ2CLQhwJBiZJb4vfk4f0GxWdEDruWKEJ1xOdo= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.5 h1:VrhDvQib/i0lxvr3zqlUwLwJP4fpmpyD9wYG1vfSu+Y= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.5/go.mod h1:k029+U8SY30/3/ras4G/Fnv/b88N4mAfliNn08Dem4M= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.10 h1:+VTRawC4iVY58pS/lzpo0lnoa/SYNGF4/B/3/U5ro8Y= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.10/go.mod h1:yifAsgBxgJWn3ggx70A3urX2AN49Y5sJTD1UQFlfqBw= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.14 h1:0jbJeuEHlwKJ9PfXtpSFc4MF+WIWORdhN1n30ITZGFM= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.14/go.mod h1:sTGThjphYE4Ohw8vJiRStAcu3rbjtXRsdNB0TvZ5wwo= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.6 h1:5fFjR/ToSOzB2OQ/XqWpZBmNvmP/pJ1jOWYlFDJTjRQ= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.6/go.mod h1:qgFDZQSD/Kys7nJnVqYlWKnh0SSdMjAi0uSwON4wgYQ= +github.com/aws/smithy-go v1.24.0 h1:LpilSUItNPFr1eY85RYgTIg5eIEPtvFbskaFcmmIUnk= +github.com/aws/smithy-go v1.24.0/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0= github.com/aymanbagabas/go-udiff v0.4.1 h1:OEIrQ8maEeDBXQDoGCbbTTXYJMYRCRO1fnodZ12Gv5o= github.com/aymanbagabas/go-udiff v0.4.1/go.mod h1:0L9PGwj20lrtmEMeyw4WKJ/TMyDtvAoK9bf2u/mNo3w= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= @@ -117,14 +110,10 @@ github.com/clipperhouse/displaywidth v0.11.0 h1:lBc6kY44VFw+TDx4I8opi/EtL9m20WSE github.com/clipperhouse/displaywidth v0.11.0/go.mod h1:bkrFNkf81G8HyVqmKGxsPufD3JhNl3dSqnGhOoSD/o0= github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJv2v7Vk= github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM= -github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8= -github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4= github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 h1:6xNmx7iTtyBRev0+D/Tv1FZd4SCg8axKApyNyRsAt/w= github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5/go.mod h1:KdCmV+x/BuvyMxRnYBlmVaq4OLiKW6iRQfvC62cvdkI= github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= -github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s= -github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -137,8 +126,6 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/elliotchance/orderedmap/v3 v3.1.0 h1:j4DJ5ObEmMBt/lcwIecKcoRxIQUEnw0L804lXYDt/pg= github.com/elliotchance/orderedmap/v3 v3.1.0/go.mod h1:G+Hc2RwaZvJMcS4JpGCOyViCnGeKf0bTYCGTO4uhjSo= -github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= -github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/envoyproxy/go-control-plane v0.14.0 h1:hbG2kr4RuFj222B6+7T83thSPqLjwBIfQawTkC++2HA= github.com/envoyproxy/go-control-plane v0.14.0/go.mod h1:NcS5X47pLl/hfqxU70yPwL9ZMkUlwlKxtAohpi2wBEU= github.com/envoyproxy/go-control-plane/envoy v1.36.0 h1:yg/JjO5E7ubRyKX3m07GF3reDNEnfOboJ0QySbH736g= @@ -153,12 +140,6 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= -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.8.0 h1:I8hjc3LbBlXTtVuFNJuwYuMiHvQJDq1AT6u4DwDzZG0= -github.com/go-git/go-billy/v5 v5.8.0/go.mod h1:RpvI/rw4Vr5QA+Z60c6d6LXH0rYJo0uD5SqfmrrheCY= -github.com/go-git/go-git/v5 v5.17.2 h1:B+nkdlxdYrvyFK4GPXVU8w1U+YkbsgciIR7f2sZJ104= -github.com/go-git/go-git/v5 v5.17.2/go.mod h1:pW/VmeqkanRFqR6AljLcs7EA7FbZaN5MQqO7oZADXpo= github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -172,8 +153,6 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-task/template v0.2.0 h1:xW7ek0o65FUSTbKcSNeg2Vyf/I7wYXFgLUznptvviBE= github.com/go-task/template v0.2.0/go.mod h1:dbdoUb6qKnHQi1y6o+IdIrs0J4o/SEhSTA6bbzZmdtc= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= @@ -184,26 +163,24 @@ github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0= github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.3.14 h1:yh8ncqsbUY4shRD5dA6RlzjJaT4hi3kII+zYw8wmLb8= -github.com/googleapis/enterprise-certificate-proxy v0.3.14/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg= +github.com/googleapis/enterprise-certificate-proxy v0.3.11 h1:vAe81Msw+8tKUxi2Dqh/NZMz7475yUvmRIkXr4oN2ao= +github.com/googleapis/enterprise-certificate-proxy v0.3.11/go.mod h1:RFV7MUdlb7AgEq2v7FmMCfeSMCllAzWxFgRdusoGks8= github.com/googleapis/gax-go/v2 v2.17.0 h1:RksgfBpxqff0EZkDWYuz9q/uWsTVz+kf43LsZ1J6SMc= github.com/googleapis/gax-go/v2 v2.17.0/go.mod h1:mzaqghpQp4JDh3HvADwrat+6M3MOIDp5YKHhb9PAgDY= -github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.72 h1:vTCWu1wbdYo7PEZFem/rlr01+Un+wwVmI7wiegFdRLk= -github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.72/go.mod h1:Vn+BBgKQHVQYdVQ4NZDICE1Brb+JfaONyDHr3q07oQc= +github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.70 h1:0HADrxxqaQkGycO1JoUUA+B4FnIkuo8d2bz/hSaTFFQ= +github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.70/go.mod h1:fm2FdDCzJdtbXF7WKAMvBb5NEPouXPHFbGNYs9ShFns= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-getter v1.8.6 h1:9sQboWULaydVphxc4S64oAI4YqpuCk7nPmvbk131ebY= -github.com/hashicorp/go-getter v1.8.6/go.mod h1:nVH12eOV2P58dIiL3rsU6Fh3wLeJEKBOJzhMmzlSWoo= +github.com/hashicorp/go-getter v1.8.5 h1:DMPV5CSw5JrNg/IK7kDZt3+l2REKXOi3oAw7uYLh2NM= +github.com/hashicorp/go-getter v1.8.5/go.mod h1:WIffejwAyDSJhoVptc3UEshEMkR9O63rw34V7k43O3Q= github.com/hashicorp/go-version v1.8.0 h1:KAkNb1HAiZd1ukkxDFGmokVZe1Xy9HG6NUp+bPle2i4= github.com/hashicorp/go-version v1.8.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= 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/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE= -github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= +github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c= +github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= @@ -231,10 +208,7 @@ github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELU github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU= github.com/pierrec/lz4/v4 v4.1.22/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= -github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4= -github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -246,6 +220,8 @@ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 h1:OkMGxebDjyw0ULyrTYWeN0UNCCkmCWfjPnIA2W6oviI= +github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06/go.mod h1:+ePHsJ1keEjQtpvf9HHw0f4ZeJ0TLRsxhunSI2hYJSs= github.com/sajari/fuzzy v1.0.0 h1:+FmwVvJErsd0d0hAPlj4CxqxUtQY/fOoY0DwX4ykpRY= github.com/sajari/fuzzy v1.0.0/go.mod h1:OjYR6KxoWOe9+dOlXeiCJd4dIbED4Oo8wpS89o0pwOo= github.com/sebdah/goldie/v2 v2.8.0 h1:dZb9wR8q5++oplmEiJT+U/5KyotVD+HNGCAc5gNr8rc= @@ -253,9 +229,6 @@ github.com/sebdah/goldie/v2 v2.8.0/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvK github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= 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/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8= -github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY= github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spiffe/go-spiffe/v2 v2.6.0 h1:l+DolpxNWYgruGQVV0xsfeya3CsC7m8iBzDnMpsbLuo= @@ -263,9 +236,9 @@ github.com/spiffe/go-spiffe/v2 v2.6.0/go.mod h1:gm2SeUoMZEtpnzPNs2Csc0D/gX33k1xI github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/u-root/u-root v0.15.1-0.20251208185023-2f8c7e763cf8 h1:cq+DjLAjz3ZPwh0+G571O/jMH0c0DzReDPLjQGL2/BA= @@ -274,8 +247,6 @@ github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 h1:pyC9PaHYZFgEKFdlp3G8 github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701/go.mod h1:P3a5rG4X7tI17Nn3aOIAYr5HbIMukwXG0urG0WuL8OA= github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY= github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -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/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ= @@ -290,60 +261,49 @@ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.6 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0/go.mod h1:fvPi2qXDqFs8M4B4fmJhE92TyQs9Ydjlg3RvfUp+NbQ= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= -go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= -go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.40.0 h1:ZrPRak/kS4xI3AVXy8F7pipuDXmDsrO8Lg+yQjBLjw0= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.40.0/go.mod h1:3y6kQCWztq6hyW8Z9YxQDDm0Je9AJoFar2G0yDcmhRk= -go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= -go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= -go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= -go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg= -go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= -go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A= -go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= -go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= +go.opentelemetry.io/otel v1.40.0 h1:oA5YeOcpRTXq6NN7frwmwFR0Cn3RhTVZvXsP4duvCms= +go.opentelemetry.io/otel v1.40.0/go.mod h1:IMb+uXZUKkMXdPddhwAHm6UfOwJyh4ct1ybIlV14J0g= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.39.0 h1:5gn2urDL/FBnK8OkCfD1j3/ER79rUuTYmCvlXBKeYL8= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.39.0/go.mod h1:0fBG6ZJxhqByfFZDwSwpZGzJU671HkwpWaNe2t4VUPI= +go.opentelemetry.io/otel/metric v1.40.0 h1:rcZe317KPftE2rstWIBitCdVp89A2HqjkxR3c11+p9g= +go.opentelemetry.io/otel/metric v1.40.0/go.mod h1:ib/crwQH7N3r5kfiBZQbwrTge743UDc7DTFVZrrXnqc= +go.opentelemetry.io/otel/sdk v1.40.0 h1:KHW/jUzgo6wsPh9At46+h4upjtccTmuZCFAc9OJ71f8= +go.opentelemetry.io/otel/sdk v1.40.0/go.mod h1:Ph7EFdYvxq72Y8Li9q8KebuYUr2KoeyHx0DRMKrYBUE= +go.opentelemetry.io/otel/sdk/metric v1.40.0 h1:mtmdVqgQkeRxHgRv4qhyJduP3fYJRMX4AtAlbuWdCYw= +go.opentelemetry.io/otel/sdk/metric v1.40.0/go.mod h1:4Z2bGMf0KSK3uRjlczMOeMhKU2rhUqdWNoKcYrtcBPg= +go.opentelemetry.io/otel/trace v1.40.0 h1:WA4etStDttCSYuhwvEa8OP8I5EWu24lkOzp+ZYblVjw= +go.opentelemetry.io/otel/trace v1.40.0/go.mod h1:zeAhriXecNGP/s2SEG3+Y8X9ujcJOTqQ5RgdEJcawiA= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= -golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= -golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= +golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= +golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw= golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM= -golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0= -golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw= +golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo= +golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y= golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= -golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= -golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.41.0 h1:QCgPso/Q3RTJx2Th4bDLqML4W6iJiaXFq2/ftQF13YU= golang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A= -golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY= -golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY= -golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8= -golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA= +golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= +golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -google.golang.org/api v0.271.0 h1:cIPN4qcUc61jlh7oXu6pwOQqbJW2GqYh5PS6rB2C/JY= -google.golang.org/api v0.271.0/go.mod h1:CGT29bhwkbF+i11qkRUJb2KMKqcJ1hdFceEIRd9u64Q= +google.golang.org/api v0.267.0 h1:w+vfWPMPYeRs8qH1aYYsFX68jMls5acWl/jocfLomwE= +google.golang.org/api v0.267.0/go.mod h1:Jzc0+ZfLnyvXma3UtaTl023TdhZu6OMBP9tJ+0EmFD0= google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 h1:VQZ/yAbAtjkHgH80teYd2em3xtIkkHd7ZhqfH2N9CsM= google.golang.org/genproto v0.0.0-20260128011058-8636f8732409/go.mod h1:rxKD3IEILWEu3P44seeNOAwZN4SaoKaQ/2eTg4mM6EM= google.golang.org/genproto/googleapis/api v0.0.0-20260203192932-546029d2fa20 h1:7ei4lp52gK1uSejlA8AZl5AJjeLUOHBQscRQZUgAcu0= google.golang.org/genproto/googleapis/api v0.0.0-20260203192932-546029d2fa20/go.mod h1:ZdbssH/1SOVnjnDlXzxDHK2MCidiqXtbYccJNzNYPEE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260203192932-546029d2fa20 h1:Jr5R2J6F6qWyzINc+4AM8t5pfUz6beZpHp678GNrMbE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260203192932-546029d2fa20/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE= google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= @@ -352,13 +312,12 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= mvdan.cc/sh/moreinterp v0.0.0-20260120230322-19def062a997 h1:3bbJwtPFh98dJ6lxRdR3eLHTH1CmR3BcU6TriIMiXjE= mvdan.cc/sh/moreinterp v0.0.0-20260120230322-19def062a997/go.mod h1:Qy/zdaMDxq9sT72Gi43K3gsV+TtTohyDO3f1cyBVwuo= -mvdan.cc/sh/v3 v3.13.1 h1:DP3TfgZhDkT7lerUdnp6PTGKyxxzz6T+cOlY/xEvfWk= -mvdan.cc/sh/v3 v3.13.1/go.mod h1:lXJ8SexMvEVcHCoDvAGLZgFJ9Wsm2sulmoNEXGhYZD0= +mvdan.cc/sh/v3 v3.13.0 h1:dSfq/MVsY4w0Vsi6Lbs0IcQquMVqLdKLESAOZjuHdLg= +mvdan.cc/sh/v3 v3.13.0/go.mod h1:KV1GByGPc/Ho0X1E6Uz9euhsIQEj4hwyKnodLlFLoDM= diff --git a/internal/fingerprint/gitignore.go b/internal/fingerprint/gitignore.go index 0b9ad2053d..43b40671e0 100644 --- a/internal/fingerprint/gitignore.go +++ b/internal/fingerprint/gitignore.go @@ -1,58 +1,82 @@ package fingerprint import ( + "bufio" + "os" "path/filepath" "strings" - "github.com/go-git/go-git/v5" - "github.com/go-git/go-git/v5/plumbing/format/gitignore" + ignore "github.com/sabhiram/go-gitignore" ) -// filterGitignored removes entries from the file map that match gitignore rules. -// Files are expected to be absolute paths. The dir parameter is used to find the git repository. -// Returns the input map unchanged if the directory is not inside a git repository. -func filterGitignored(files map[string]bool, dir string) map[string]bool { - repo, err := git.PlainOpenWithOptions(dir, &git.PlainOpenOptions{ - DetectDotGit: true, - }) - if err != nil { - return files - } - - wt, err := repo.Worktree() - if err != nil { - return files - } +type gitignoreRule struct { + dir string + matcher *ignore.GitIgnore +} - var allPatterns []gitignore.Pattern +// loadGitignoreRules reads .gitignore files walking up from dir to rootDir. +func loadGitignoreRules(rootDir, dir string) []gitignoreRule { + rootDir, _ = filepath.Abs(rootDir) + dir, _ = filepath.Abs(dir) - if ps, err := gitignore.LoadSystemPatterns(wt.Filesystem); err == nil { - allPatterns = append(allPatterns, ps...) + var rules []gitignoreRule + current := dir + for { + lines := readGitignoreLines(filepath.Join(current, ".gitignore")) + if len(lines) > 0 { + rules = append(rules, gitignoreRule{ + dir: current, + matcher: ignore.CompileIgnoreLines(lines...), + }) + } + if current == rootDir { + break + } + parent := filepath.Dir(current) + if parent == current { + break + } + current = parent } - if ps, err := gitignore.LoadGlobalPatterns(wt.Filesystem); err == nil { - allPatterns = append(allPatterns, ps...) + return rules +} + +func readGitignoreLines(path string) []string { + f, err := os.Open(path) + if err != nil { + return nil } + defer f.Close() - if ps, err := gitignore.ReadPatterns(wt.Filesystem, nil); err == nil { - allPatterns = append(allPatterns, ps...) + var lines []string + scanner := bufio.NewScanner(f) + for scanner.Scan() { + line := scanner.Text() + if line != "" && !strings.HasPrefix(line, "#") { + lines = append(lines, line) + } } + return lines +} - if len(allPatterns) == 0 { +// filterGitignored removes entries from the file map that match gitignore rules. +func filterGitignored(files map[string]bool, rootDir, dir string) map[string]bool { + rules := loadGitignoreRules(rootDir, dir) + if len(rules) == 0 { return files } - matcher := gitignore.NewMatcher(allPatterns) - gitRoot := wt.Filesystem.Root() - for path := range files { - relPath, err := filepath.Rel(gitRoot, path) - if err != nil { - continue - } - pathComponents := strings.Split(filepath.ToSlash(relPath), "/") - if matcher.Match(pathComponents, false) { - files[path] = false + for _, rule := range rules { + relPath, err := filepath.Rel(rule.dir, path) + if err != nil || strings.HasPrefix(relPath, "..") { + continue + } + if rule.matcher.MatchesPath(filepath.ToSlash(relPath)) { + files[path] = false + break + } } } diff --git a/internal/fingerprint/gitignore_test.go b/internal/fingerprint/gitignore_test.go index 8eb0dbfdbb..2a09fdb655 100644 --- a/internal/fingerprint/gitignore_test.go +++ b/internal/fingerprint/gitignore_test.go @@ -5,7 +5,6 @@ import ( "path/filepath" "testing" - "github.com/go-git/go-git/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -14,8 +13,7 @@ import ( func initGitRepo(t *testing.T, dir string) { t.Helper() - _, err := git.PlainInit(dir, false) - require.NoError(t, err) + require.NoError(t, os.MkdirAll(filepath.Join(dir, ".git"), 0o755)) } func TestGlobsWithGitignore(t *testing.T) { @@ -27,27 +25,21 @@ func TestGlobsWithGitignore(t *testing.T) { initGitRepo(t, dir) - // Create test files require.NoError(t, os.WriteFile(filepath.Join(dir, "included.txt"), []byte("included"), 0o644)) require.NoError(t, os.WriteFile(filepath.Join(dir, "ignored.log"), []byte("ignored"), 0o644)) require.NoError(t, os.WriteFile(filepath.Join(dir, "also-included.txt"), []byte("also included"), 0o644)) - - // Create .gitignore require.NoError(t, os.WriteFile(filepath.Join(dir, ".gitignore"), []byte("*.log\n"), 0o644)) globs := []*ast.Glob{ {Glob: "./*"}, } - // Without gitignore - should include all files - filesWithout, err := Globs(dir, globs, false) + filesWithout, err := Globs(dir, globs, false, dir) require.NoError(t, err) - // With gitignore - should exclude .log files - filesWith, err := Globs(dir, globs, true) + filesWith, err := Globs(dir, globs, true, dir) require.NoError(t, err) - // The .log file should be in the unfiltered list hasLog := false for _, f := range filesWithout { if filepath.Base(f) == "ignored.log" { @@ -57,7 +49,6 @@ func TestGlobsWithGitignore(t *testing.T) { } assert.True(t, hasLog, "ignored.log should be present without gitignore filter") - // The .log file should NOT be in the filtered list hasLog = false for _, f := range filesWith { if filepath.Base(f) == "ignored.log" { @@ -67,7 +58,6 @@ func TestGlobsWithGitignore(t *testing.T) { } assert.False(t, hasLog, "ignored.log should be excluded with gitignore filter") - // .txt files should still be present txtCount := 0 for _, f := range filesWith { if filepath.Ext(f) == ".txt" { @@ -77,34 +67,36 @@ func TestGlobsWithGitignore(t *testing.T) { assert.Equal(t, 2, txtCount, "both .txt files should remain") } -func TestGlobsWithGitignoreDisabled(t *testing.T) { +func TestGlobsWithGitignoreNested(t *testing.T) { t.Parallel() - dir, err := os.MkdirTemp("", "task-gitignore-disabled-*") + dir, err := os.MkdirTemp("", "task-gitignore-nested-*") require.NoError(t, err) t.Cleanup(func() { os.RemoveAll(dir) }) initGitRepo(t, dir) - require.NoError(t, os.WriteFile(filepath.Join(dir, "file.txt"), []byte("content"), 0o644)) - require.NoError(t, os.WriteFile(filepath.Join(dir, "file.log"), []byte("content"), 0o644)) + + subDir := filepath.Join(dir, "sub") + require.NoError(t, os.MkdirAll(subDir, 0o755)) + + require.NoError(t, os.WriteFile(filepath.Join(subDir, "keep.txt"), []byte("keep"), 0o644)) + require.NoError(t, os.WriteFile(filepath.Join(subDir, "build.out"), []byte("build"), 0o644)) + + // Root .gitignore ignores *.log require.NoError(t, os.WriteFile(filepath.Join(dir, ".gitignore"), []byte("*.log\n"), 0o644)) + // Nested .gitignore ignores *.out + require.NoError(t, os.WriteFile(filepath.Join(subDir, ".gitignore"), []byte("*.out\n"), 0o644)) globs := []*ast.Glob{ {Glob: "./*"}, } - // WithGitignore(false, ...) should not filter - files, err := Globs(dir, globs, false) + files, err := Globs(subDir, globs, true, dir) require.NoError(t, err) - hasLog := false for _, f := range files { - if filepath.Base(f) == "file.log" { - hasLog = true - break - } + assert.NotEqual(t, "build.out", filepath.Base(f), "build.out should be excluded by nested .gitignore") } - assert.True(t, hasLog, "file.log should be present when gitignore is disabled") } func TestGlobsWithGitignoreNoRepo(t *testing.T) { @@ -120,8 +112,7 @@ func TestGlobsWithGitignoreNoRepo(t *testing.T) { {Glob: "./*"}, } - // Should not error and should return all files - files, err := Globs(dir, globs, true) + files, err := Globs(dir, globs, true, dir) require.NoError(t, err) assert.Len(t, files, 1) } diff --git a/internal/fingerprint/glob.go b/internal/fingerprint/glob.go index c87c9ec3b5..f19da358b4 100644 --- a/internal/fingerprint/glob.go +++ b/internal/fingerprint/glob.go @@ -10,7 +10,7 @@ import ( "github.com/go-task/task/v3/taskfile/ast" ) -func Globs(dir string, globs []*ast.Glob, gitignore bool) ([]string, error) { +func Globs(dir string, globs []*ast.Glob, gitignore bool, rootDir string) ([]string, error) { resultMap := make(map[string]bool) for _, g := range globs { matches, err := glob(dir, g.Glob) @@ -23,7 +23,7 @@ func Globs(dir string, globs []*ast.Glob, gitignore bool) ([]string, error) { } if gitignore { - resultMap = filterGitignored(resultMap, dir) + resultMap = filterGitignored(resultMap, rootDir, dir) } return collectKeys(resultMap), nil diff --git a/internal/fingerprint/sources.go b/internal/fingerprint/sources.go index 34d3a04bee..54303a464d 100644 --- a/internal/fingerprint/sources.go +++ b/internal/fingerprint/sources.go @@ -2,12 +2,12 @@ package fingerprint import "fmt" -func NewSourcesChecker(method, tempDir string, dry bool) (SourcesCheckable, error) { +func NewSourcesChecker(method, tempDir string, dry bool, rootDir string) (SourcesCheckable, error) { switch method { case "timestamp": - return NewTimestampChecker(tempDir, dry), nil + return NewTimestampChecker(tempDir, dry, rootDir), nil case "checksum": - return NewChecksumChecker(tempDir, dry), nil + return NewChecksumChecker(tempDir, dry, rootDir), nil case "none": return NoneChecker{}, nil default: diff --git a/internal/fingerprint/sources_checksum.go b/internal/fingerprint/sources_checksum.go index ef9e7387b3..94a97a6db5 100644 --- a/internal/fingerprint/sources_checksum.go +++ b/internal/fingerprint/sources_checksum.go @@ -19,12 +19,14 @@ import ( type ChecksumChecker struct { tempDir string dry bool + rootDir string } -func NewChecksumChecker(tempDir string, dry bool) *ChecksumChecker { +func NewChecksumChecker(tempDir string, dry bool, rootDir string) *ChecksumChecker { return &ChecksumChecker{ tempDir: tempDir, dry: dry, + rootDir: rootDir, } } @@ -89,7 +91,7 @@ func (*ChecksumChecker) Kind() string { } func (c *ChecksumChecker) checksum(t *ast.Task) (string, error) { - sources, err := Globs(t.Dir, t.Sources, t.IsGitignore()) + sources, err := Globs(t.Dir, t.Sources, t.IsGitignore(), c.rootDir) if err != nil { return "", err } diff --git a/internal/fingerprint/sources_timestamp.go b/internal/fingerprint/sources_timestamp.go index 5d48285193..003e0a2608 100644 --- a/internal/fingerprint/sources_timestamp.go +++ b/internal/fingerprint/sources_timestamp.go @@ -13,12 +13,14 @@ import ( type TimestampChecker struct { tempDir string dry bool + rootDir string } -func NewTimestampChecker(tempDir string, dry bool) *TimestampChecker { +func NewTimestampChecker(tempDir string, dry bool, rootDir string) *TimestampChecker { return &TimestampChecker{ tempDir: tempDir, dry: dry, + rootDir: rootDir, } } @@ -28,7 +30,7 @@ func (checker *TimestampChecker) IsUpToDate(t *ast.Task) (bool, error) { return false, nil } - sources, err := Globs(t.Dir, t.Sources, t.IsGitignore()) + sources, err := Globs(t.Dir, t.Sources, t.IsGitignore(), checker.rootDir) if err != nil { return false, nil } @@ -54,7 +56,7 @@ func (checker *TimestampChecker) IsUpToDate(t *ast.Task) (bool, error) { } } - generates, err := Globs(t.Dir, t.Generates, t.IsGitignore()) + generates, err := Globs(t.Dir, t.Generates, t.IsGitignore(), checker.rootDir) if err != nil { return false, nil } @@ -112,7 +114,7 @@ func (checker *TimestampChecker) Kind() string { // Value implements the Checker Interface func (checker *TimestampChecker) Value(t *ast.Task) (any, error) { - sources, err := Globs(t.Dir, t.Sources, t.IsGitignore()) + sources, err := Globs(t.Dir, t.Sources, t.IsGitignore(), checker.rootDir) if err != nil { return time.Now(), err } diff --git a/internal/fingerprint/task.go b/internal/fingerprint/task.go index 2b48e114c9..ca8e18b9ab 100644 --- a/internal/fingerprint/task.go +++ b/internal/fingerprint/task.go @@ -13,6 +13,7 @@ type ( method string dry bool tempDir string + rootDir string logger *logger.Logger statusChecker StatusCheckable sourcesChecker SourcesCheckable @@ -37,6 +38,12 @@ func WithTempDir(tempDir string) CheckerOption { } } +func WithRootDir(rootDir string) CheckerOption { + return func(config *CheckerConfig) { + config.rootDir = rootDir + } +} + func WithLogger(logger *logger.Logger) CheckerOption { return func(config *CheckerConfig) { config.logger = logger @@ -86,7 +93,7 @@ func IsTaskUpToDate( // If no sources checker was given, set up the default one if config.sourcesChecker == nil { - config.sourcesChecker, err = NewSourcesChecker(config.method, config.tempDir, config.dry) + config.sourcesChecker, err = NewSourcesChecker(config.method, config.tempDir, config.dry, config.rootDir) if err != nil { return false, err } diff --git a/status.go b/status.go index ae40f5ba5f..8680d52704 100644 --- a/status.go +++ b/status.go @@ -46,7 +46,7 @@ func (e *Executor) statusOnError(t *ast.Task) error { if method == "" { method = e.Taskfile.Method } - checker, err := fingerprint.NewSourcesChecker(method, e.TempDir.Fingerprint, e.Dry) + checker, err := fingerprint.NewSourcesChecker(method, e.TempDir.Fingerprint, e.Dry, e.Dir) if err != nil { return err } diff --git a/task.go b/task.go index 54cda92762..fa2842e4f6 100644 --- a/task.go +++ b/task.go @@ -231,6 +231,7 @@ func (e *Executor) RunTask(ctx context.Context, call *Call) error { fingerprint.WithTempDir(e.TempDir.Fingerprint), fingerprint.WithDry(e.Dry), fingerprint.WithLogger(e.Logger), + fingerprint.WithRootDir(e.Dir), ) if err != nil { return err diff --git a/variables.go b/variables.go index 18d716a548..7f4054bf06 100644 --- a/variables.go +++ b/variables.go @@ -203,9 +203,9 @@ func (e *Executor) compiledTask(call *Call, evaluateShVars bool) (*ast.Task, err var checker fingerprint.SourcesCheckable if origTask.Method == "timestamp" { - checker = fingerprint.NewTimestampChecker(e.TempDir.Fingerprint, e.Dry) + checker = fingerprint.NewTimestampChecker(e.TempDir.Fingerprint, e.Dry, e.Dir) } else { - checker = fingerprint.NewChecksumChecker(e.TempDir.Fingerprint, e.Dry) + checker = fingerprint.NewChecksumChecker(e.TempDir.Fingerprint, e.Dry, e.Dir) } value, err := checker.Value(&new) @@ -226,7 +226,7 @@ func (e *Executor) compiledTask(call *Call, evaluateShVars bool) (*ast.Task, err continue } if cmd.For != nil { - list, keys, err := itemsFromFor(cmd.For, new.Dir, new.Sources, new.Generates, gitignore, vars, origTask.Location, cache) + list, keys, err := itemsFromFor(cmd.For, new.Dir, new.Sources, new.Generates, gitignore, e.Dir, vars, origTask.Location, cache) if err != nil { return nil, err } @@ -275,7 +275,7 @@ func (e *Executor) compiledTask(call *Call, evaluateShVars bool) (*ast.Task, err continue } if dep.For != nil { - list, keys, err := itemsFromFor(dep.For, new.Dir, new.Sources, new.Generates, gitignore, vars, origTask.Location, cache) + list, keys, err := itemsFromFor(dep.For, new.Dir, new.Sources, new.Generates, gitignore, e.Dir, vars, origTask.Location, cache) if err != nil { return nil, err } @@ -347,6 +347,7 @@ func itemsFromFor( sources []*ast.Glob, generates []*ast.Glob, gitignore bool, + rootDir string, vars *ast.Vars, location *ast.Location, cache *templater.Cache, @@ -369,7 +370,7 @@ func itemsFromFor( } // Get the list from the task sources if f.From == "sources" { - glist, err := fingerprint.Globs(dir, sources, gitignore) + glist, err := fingerprint.Globs(dir, sources, gitignore, rootDir) if err != nil { return nil, nil, err } @@ -383,7 +384,7 @@ func itemsFromFor( } // Get the list from the task generates if f.From == "generates" { - glist, err := fingerprint.Globs(dir, generates, gitignore) + glist, err := fingerprint.Globs(dir, generates, gitignore, rootDir) if err != nil { return nil, nil, err } diff --git a/watch.go b/watch.go index 349dd57a69..a246ae55c7 100644 --- a/watch.go +++ b/watch.go @@ -205,7 +205,7 @@ func (e *Executor) collectSources(calls []*Call) ([]string, error) { var sources []string err := e.traverse(calls, func(task *ast.Task) error { - files, err := fingerprint.Globs(task.Dir, task.Sources, task.IsGitignore()) + files, err := fingerprint.Globs(task.Dir, task.Sources, task.IsGitignore(), e.Dir) if err != nil { return err } From 78e057e9cb61713c602adb420096e54ef6268c92 Mon Sep 17 00:00:00 2001 From: Valentin Maerten Date: Sat, 4 Apr 2026 10:29:45 +0200 Subject: [PATCH 3/6] wip --- internal/fingerprint/gitignore.go | 20 ++++++++++++++------ internal/fingerprint/gitignore_test.go | 8 ++++---- internal/fingerprint/glob.go | 4 ++-- internal/fingerprint/sources.go | 6 +++--- internal/fingerprint/sources_checksum.go | 6 ++---- internal/fingerprint/sources_timestamp.go | 10 ++++------ internal/fingerprint/task.go | 9 +-------- status.go | 2 +- task.go | 1 - variables.go | 13 ++++++------- watch.go | 2 +- 11 files changed, 38 insertions(+), 43 deletions(-) diff --git a/internal/fingerprint/gitignore.go b/internal/fingerprint/gitignore.go index 43b40671e0..62287f0d8a 100644 --- a/internal/fingerprint/gitignore.go +++ b/internal/fingerprint/gitignore.go @@ -14,13 +14,16 @@ type gitignoreRule struct { matcher *ignore.GitIgnore } -// loadGitignoreRules reads .gitignore files walking up from dir to rootDir. -func loadGitignoreRules(rootDir, dir string) []gitignoreRule { - rootDir, _ = filepath.Abs(rootDir) +// loadGitignoreRules walks up from dir collecting .gitignore files. +// Stops at the first .git (file or directory) found. +// Returns nil if no .git is found (not in a git repo). +func loadGitignoreRules(dir string) []gitignoreRule { dir, _ = filepath.Abs(dir) var rules []gitignoreRule + foundGit := false current := dir + for { lines := readGitignoreLines(filepath.Join(current, ".gitignore")) if len(lines) > 0 { @@ -29,7 +32,8 @@ func loadGitignoreRules(rootDir, dir string) []gitignoreRule { matcher: ignore.CompileIgnoreLines(lines...), }) } - if current == rootDir { + if _, err := os.Stat(filepath.Join(current, ".git")); err == nil { + foundGit = true break } parent := filepath.Dir(current) @@ -39,6 +43,10 @@ func loadGitignoreRules(rootDir, dir string) []gitignoreRule { current = parent } + if !foundGit { + return nil + } + return rules } @@ -61,8 +69,8 @@ func readGitignoreLines(path string) []string { } // filterGitignored removes entries from the file map that match gitignore rules. -func filterGitignored(files map[string]bool, rootDir, dir string) map[string]bool { - rules := loadGitignoreRules(rootDir, dir) +func filterGitignored(files map[string]bool, dir string) map[string]bool { + rules := loadGitignoreRules(dir) if len(rules) == 0 { return files } diff --git a/internal/fingerprint/gitignore_test.go b/internal/fingerprint/gitignore_test.go index 2a09fdb655..1c5118f884 100644 --- a/internal/fingerprint/gitignore_test.go +++ b/internal/fingerprint/gitignore_test.go @@ -34,10 +34,10 @@ func TestGlobsWithGitignore(t *testing.T) { {Glob: "./*"}, } - filesWithout, err := Globs(dir, globs, false, dir) + filesWithout, err := Globs(dir, globs, false) require.NoError(t, err) - filesWith, err := Globs(dir, globs, true, dir) + filesWith, err := Globs(dir, globs, true) require.NoError(t, err) hasLog := false @@ -91,7 +91,7 @@ func TestGlobsWithGitignoreNested(t *testing.T) { {Glob: "./*"}, } - files, err := Globs(subDir, globs, true, dir) + files, err := Globs(subDir, globs, true) require.NoError(t, err) for _, f := range files { @@ -112,7 +112,7 @@ func TestGlobsWithGitignoreNoRepo(t *testing.T) { {Glob: "./*"}, } - files, err := Globs(dir, globs, true, dir) + files, err := Globs(dir, globs, true) require.NoError(t, err) assert.Len(t, files, 1) } diff --git a/internal/fingerprint/glob.go b/internal/fingerprint/glob.go index f19da358b4..c87c9ec3b5 100644 --- a/internal/fingerprint/glob.go +++ b/internal/fingerprint/glob.go @@ -10,7 +10,7 @@ import ( "github.com/go-task/task/v3/taskfile/ast" ) -func Globs(dir string, globs []*ast.Glob, gitignore bool, rootDir string) ([]string, error) { +func Globs(dir string, globs []*ast.Glob, gitignore bool) ([]string, error) { resultMap := make(map[string]bool) for _, g := range globs { matches, err := glob(dir, g.Glob) @@ -23,7 +23,7 @@ func Globs(dir string, globs []*ast.Glob, gitignore bool, rootDir string) ([]str } if gitignore { - resultMap = filterGitignored(resultMap, rootDir, dir) + resultMap = filterGitignored(resultMap, dir) } return collectKeys(resultMap), nil diff --git a/internal/fingerprint/sources.go b/internal/fingerprint/sources.go index 54303a464d..34d3a04bee 100644 --- a/internal/fingerprint/sources.go +++ b/internal/fingerprint/sources.go @@ -2,12 +2,12 @@ package fingerprint import "fmt" -func NewSourcesChecker(method, tempDir string, dry bool, rootDir string) (SourcesCheckable, error) { +func NewSourcesChecker(method, tempDir string, dry bool) (SourcesCheckable, error) { switch method { case "timestamp": - return NewTimestampChecker(tempDir, dry, rootDir), nil + return NewTimestampChecker(tempDir, dry), nil case "checksum": - return NewChecksumChecker(tempDir, dry, rootDir), nil + return NewChecksumChecker(tempDir, dry), nil case "none": return NoneChecker{}, nil default: diff --git a/internal/fingerprint/sources_checksum.go b/internal/fingerprint/sources_checksum.go index 94a97a6db5..ef9e7387b3 100644 --- a/internal/fingerprint/sources_checksum.go +++ b/internal/fingerprint/sources_checksum.go @@ -19,14 +19,12 @@ import ( type ChecksumChecker struct { tempDir string dry bool - rootDir string } -func NewChecksumChecker(tempDir string, dry bool, rootDir string) *ChecksumChecker { +func NewChecksumChecker(tempDir string, dry bool) *ChecksumChecker { return &ChecksumChecker{ tempDir: tempDir, dry: dry, - rootDir: rootDir, } } @@ -91,7 +89,7 @@ func (*ChecksumChecker) Kind() string { } func (c *ChecksumChecker) checksum(t *ast.Task) (string, error) { - sources, err := Globs(t.Dir, t.Sources, t.IsGitignore(), c.rootDir) + sources, err := Globs(t.Dir, t.Sources, t.IsGitignore()) if err != nil { return "", err } diff --git a/internal/fingerprint/sources_timestamp.go b/internal/fingerprint/sources_timestamp.go index 003e0a2608..5d48285193 100644 --- a/internal/fingerprint/sources_timestamp.go +++ b/internal/fingerprint/sources_timestamp.go @@ -13,14 +13,12 @@ import ( type TimestampChecker struct { tempDir string dry bool - rootDir string } -func NewTimestampChecker(tempDir string, dry bool, rootDir string) *TimestampChecker { +func NewTimestampChecker(tempDir string, dry bool) *TimestampChecker { return &TimestampChecker{ tempDir: tempDir, dry: dry, - rootDir: rootDir, } } @@ -30,7 +28,7 @@ func (checker *TimestampChecker) IsUpToDate(t *ast.Task) (bool, error) { return false, nil } - sources, err := Globs(t.Dir, t.Sources, t.IsGitignore(), checker.rootDir) + sources, err := Globs(t.Dir, t.Sources, t.IsGitignore()) if err != nil { return false, nil } @@ -56,7 +54,7 @@ func (checker *TimestampChecker) IsUpToDate(t *ast.Task) (bool, error) { } } - generates, err := Globs(t.Dir, t.Generates, t.IsGitignore(), checker.rootDir) + generates, err := Globs(t.Dir, t.Generates, t.IsGitignore()) if err != nil { return false, nil } @@ -114,7 +112,7 @@ func (checker *TimestampChecker) Kind() string { // Value implements the Checker Interface func (checker *TimestampChecker) Value(t *ast.Task) (any, error) { - sources, err := Globs(t.Dir, t.Sources, t.IsGitignore(), checker.rootDir) + sources, err := Globs(t.Dir, t.Sources, t.IsGitignore()) if err != nil { return time.Now(), err } diff --git a/internal/fingerprint/task.go b/internal/fingerprint/task.go index ca8e18b9ab..2b48e114c9 100644 --- a/internal/fingerprint/task.go +++ b/internal/fingerprint/task.go @@ -13,7 +13,6 @@ type ( method string dry bool tempDir string - rootDir string logger *logger.Logger statusChecker StatusCheckable sourcesChecker SourcesCheckable @@ -38,12 +37,6 @@ func WithTempDir(tempDir string) CheckerOption { } } -func WithRootDir(rootDir string) CheckerOption { - return func(config *CheckerConfig) { - config.rootDir = rootDir - } -} - func WithLogger(logger *logger.Logger) CheckerOption { return func(config *CheckerConfig) { config.logger = logger @@ -93,7 +86,7 @@ func IsTaskUpToDate( // If no sources checker was given, set up the default one if config.sourcesChecker == nil { - config.sourcesChecker, err = NewSourcesChecker(config.method, config.tempDir, config.dry, config.rootDir) + config.sourcesChecker, err = NewSourcesChecker(config.method, config.tempDir, config.dry) if err != nil { return false, err } diff --git a/status.go b/status.go index 8680d52704..ae40f5ba5f 100644 --- a/status.go +++ b/status.go @@ -46,7 +46,7 @@ func (e *Executor) statusOnError(t *ast.Task) error { if method == "" { method = e.Taskfile.Method } - checker, err := fingerprint.NewSourcesChecker(method, e.TempDir.Fingerprint, e.Dry, e.Dir) + checker, err := fingerprint.NewSourcesChecker(method, e.TempDir.Fingerprint, e.Dry) if err != nil { return err } diff --git a/task.go b/task.go index fa2842e4f6..54cda92762 100644 --- a/task.go +++ b/task.go @@ -231,7 +231,6 @@ func (e *Executor) RunTask(ctx context.Context, call *Call) error { fingerprint.WithTempDir(e.TempDir.Fingerprint), fingerprint.WithDry(e.Dry), fingerprint.WithLogger(e.Logger), - fingerprint.WithRootDir(e.Dir), ) if err != nil { return err diff --git a/variables.go b/variables.go index 7f4054bf06..18d716a548 100644 --- a/variables.go +++ b/variables.go @@ -203,9 +203,9 @@ func (e *Executor) compiledTask(call *Call, evaluateShVars bool) (*ast.Task, err var checker fingerprint.SourcesCheckable if origTask.Method == "timestamp" { - checker = fingerprint.NewTimestampChecker(e.TempDir.Fingerprint, e.Dry, e.Dir) + checker = fingerprint.NewTimestampChecker(e.TempDir.Fingerprint, e.Dry) } else { - checker = fingerprint.NewChecksumChecker(e.TempDir.Fingerprint, e.Dry, e.Dir) + checker = fingerprint.NewChecksumChecker(e.TempDir.Fingerprint, e.Dry) } value, err := checker.Value(&new) @@ -226,7 +226,7 @@ func (e *Executor) compiledTask(call *Call, evaluateShVars bool) (*ast.Task, err continue } if cmd.For != nil { - list, keys, err := itemsFromFor(cmd.For, new.Dir, new.Sources, new.Generates, gitignore, e.Dir, vars, origTask.Location, cache) + list, keys, err := itemsFromFor(cmd.For, new.Dir, new.Sources, new.Generates, gitignore, vars, origTask.Location, cache) if err != nil { return nil, err } @@ -275,7 +275,7 @@ func (e *Executor) compiledTask(call *Call, evaluateShVars bool) (*ast.Task, err continue } if dep.For != nil { - list, keys, err := itemsFromFor(dep.For, new.Dir, new.Sources, new.Generates, gitignore, e.Dir, vars, origTask.Location, cache) + list, keys, err := itemsFromFor(dep.For, new.Dir, new.Sources, new.Generates, gitignore, vars, origTask.Location, cache) if err != nil { return nil, err } @@ -347,7 +347,6 @@ func itemsFromFor( sources []*ast.Glob, generates []*ast.Glob, gitignore bool, - rootDir string, vars *ast.Vars, location *ast.Location, cache *templater.Cache, @@ -370,7 +369,7 @@ func itemsFromFor( } // Get the list from the task sources if f.From == "sources" { - glist, err := fingerprint.Globs(dir, sources, gitignore, rootDir) + glist, err := fingerprint.Globs(dir, sources, gitignore) if err != nil { return nil, nil, err } @@ -384,7 +383,7 @@ func itemsFromFor( } // Get the list from the task generates if f.From == "generates" { - glist, err := fingerprint.Globs(dir, generates, gitignore, rootDir) + glist, err := fingerprint.Globs(dir, generates, gitignore) if err != nil { return nil, nil, err } diff --git a/watch.go b/watch.go index a246ae55c7..349dd57a69 100644 --- a/watch.go +++ b/watch.go @@ -205,7 +205,7 @@ func (e *Executor) collectSources(calls []*Call) ([]string, error) { var sources []string err := e.traverse(calls, func(task *ast.Task) error { - files, err := fingerprint.Globs(task.Dir, task.Sources, task.IsGitignore(), e.Dir) + files, err := fingerprint.Globs(task.Dir, task.Sources, task.IsGitignore()) if err != nil { return err } From 43e28d9d0b0e446cd11169a0839b5eaba8a5dbaa Mon Sep 17 00:00:00 2001 From: Valentin Maerten Date: Sat, 4 Apr 2026 10:44:35 +0200 Subject: [PATCH 4/6] refactor: remove rootDir param, auto-detect .git as boundary Walk up from task dir to find .git instead of threading rootDir through Globs, checkers, and itemsFromFor. Gitignore rules are discarded if no .git is found, matching ripgrep's require_git behavior. This keeps the Globs signature clean and makes the future .taskignore integration straightforward (loaded at setup like .taskrc, separate boundary). --- internal/fingerprint/gitignore_test.go | 16 +++------- taskfile/ast/task.go | 2 +- taskfile/ast/taskfile.go | 44 +++++++++++++------------- 3 files changed, 28 insertions(+), 34 deletions(-) diff --git a/internal/fingerprint/gitignore_test.go b/internal/fingerprint/gitignore_test.go index 1c5118f884..edef18b1af 100644 --- a/internal/fingerprint/gitignore_test.go +++ b/internal/fingerprint/gitignore_test.go @@ -19,10 +19,7 @@ func initGitRepo(t *testing.T, dir string) { func TestGlobsWithGitignore(t *testing.T) { t.Parallel() - dir, err := os.MkdirTemp("", "task-gitignore-test-*") - require.NoError(t, err) - t.Cleanup(func() { os.RemoveAll(dir) }) - + dir := t.TempDir() initGitRepo(t, dir) require.NoError(t, os.WriteFile(filepath.Join(dir, "included.txt"), []byte("included"), 0o644)) @@ -70,10 +67,7 @@ func TestGlobsWithGitignore(t *testing.T) { func TestGlobsWithGitignoreNested(t *testing.T) { t.Parallel() - dir, err := os.MkdirTemp("", "task-gitignore-nested-*") - require.NoError(t, err) - t.Cleanup(func() { os.RemoveAll(dir) }) - + dir := t.TempDir() initGitRepo(t, dir) subDir := filepath.Join(dir, "sub") @@ -82,9 +76,7 @@ func TestGlobsWithGitignoreNested(t *testing.T) { require.NoError(t, os.WriteFile(filepath.Join(subDir, "keep.txt"), []byte("keep"), 0o644)) require.NoError(t, os.WriteFile(filepath.Join(subDir, "build.out"), []byte("build"), 0o644)) - // Root .gitignore ignores *.log require.NoError(t, os.WriteFile(filepath.Join(dir, ".gitignore"), []byte("*.log\n"), 0o644)) - // Nested .gitignore ignores *.out require.NoError(t, os.WriteFile(filepath.Join(subDir, ".gitignore"), []byte("*.out\n"), 0o644)) globs := []*ast.Glob{ @@ -102,7 +94,9 @@ func TestGlobsWithGitignoreNested(t *testing.T) { func TestGlobsWithGitignoreNoRepo(t *testing.T) { t.Parallel() - dir, err := os.MkdirTemp("", "task-gitignore-norepo-*") + // Cannot use t.TempDir() here because it creates a dir inside the + // go-task repo which has a .git parent, defeating the "no repo" test. + dir, err := os.MkdirTemp("", "task-gitignore-norepo-*") //nolint:usetesting require.NoError(t, err) t.Cleanup(func() { os.RemoveAll(dir) }) diff --git a/taskfile/ast/task.go b/taskfile/ast/task.go index 30212ab613..f7f0f31870 100644 --- a/taskfile/ast/task.go +++ b/taskfile/ast/task.go @@ -156,7 +156,7 @@ func (t *Task) UnmarshalYAML(node *yaml.Node) error { Internal bool Method string Prefix string - IgnoreError bool `yaml:"ignore_error"` + IgnoreError bool `yaml:"ignore_error"` Gitignore *bool `yaml:"gitignore,omitempty"` Run string Platforms []*Platform diff --git a/taskfile/ast/taskfile.go b/taskfile/ast/taskfile.go index 9216f39660..125b2670e0 100644 --- a/taskfile/ast/taskfile.go +++ b/taskfile/ast/taskfile.go @@ -20,16 +20,16 @@ var ErrIncludedTaskfilesCantHaveDotenvs = errors.New("task: Included Taskfiles c // Taskfile is the abstract syntax tree for a Taskfile type Taskfile struct { - Location string - Version *semver.Version - Output Output - Method string - Includes *Includes - Set []string - Shopt []string - Vars *Vars - Env *Vars - Tasks *Tasks + Location string + Version *semver.Version + Output Output + Method string + Includes *Includes + Set []string + Shopt []string + Vars *Vars + Env *Vars + Tasks *Tasks Silent bool Dotenv []string Run string @@ -77,18 +77,18 @@ func (tf *Taskfile) UnmarshalYAML(node *yaml.Node) error { switch node.Kind { case yaml.MappingNode: var taskfile struct { - Version *semver.Version - Output Output - Method string - Includes *Includes - Set []string - Shopt []string - Vars *Vars - Env *Vars - Tasks *Tasks - Silent bool - Dotenv []string - Run string + Version *semver.Version + Output Output + Method string + Includes *Includes + Set []string + Shopt []string + Vars *Vars + Env *Vars + Tasks *Tasks + Silent bool + Dotenv []string + Run string Interval time.Duration Gitignore bool } From 37d6b7155f290be229b60c40a8ff042d392331f1 Mon Sep 17 00:00:00 2001 From: Valentin Maerten Date: Sat, 4 Apr 2026 13:05:01 +0200 Subject: [PATCH 5/6] rename: gitignore -> use_gitignore for clarity Rename the Taskfile/task option from `gitignore` to `use_gitignore` to avoid ambiguity (could be read as "ignore git" vs "use .gitignore"). Consistent with Biome's `useIgnoreFile` naming convention. --- internal/fingerprint/glob.go | 4 ++-- internal/fingerprint/sources_checksum.go | 2 +- internal/fingerprint/sources_timestamp.go | 6 +++--- taskfile/ast/task.go | 16 ++++++++-------- taskfile/ast/taskfile.go | 6 +++--- testdata/gitignore/Taskfile.yml | 6 +++--- variables.go | 10 +++++----- watch.go | 2 +- website/src/public/schema.json | 4 ++-- 9 files changed, 28 insertions(+), 28 deletions(-) diff --git a/internal/fingerprint/glob.go b/internal/fingerprint/glob.go index c87c9ec3b5..930a54a3b1 100644 --- a/internal/fingerprint/glob.go +++ b/internal/fingerprint/glob.go @@ -10,7 +10,7 @@ import ( "github.com/go-task/task/v3/taskfile/ast" ) -func Globs(dir string, globs []*ast.Glob, gitignore bool) ([]string, error) { +func Globs(dir string, globs []*ast.Glob, useGitignore bool) ([]string, error) { resultMap := make(map[string]bool) for _, g := range globs { matches, err := glob(dir, g.Glob) @@ -22,7 +22,7 @@ func Globs(dir string, globs []*ast.Glob, gitignore bool) ([]string, error) { } } - if gitignore { + if useGitignore { resultMap = filterGitignored(resultMap, dir) } diff --git a/internal/fingerprint/sources_checksum.go b/internal/fingerprint/sources_checksum.go index ef9e7387b3..9ffdbdb6f8 100644 --- a/internal/fingerprint/sources_checksum.go +++ b/internal/fingerprint/sources_checksum.go @@ -89,7 +89,7 @@ func (*ChecksumChecker) Kind() string { } func (c *ChecksumChecker) checksum(t *ast.Task) (string, error) { - sources, err := Globs(t.Dir, t.Sources, t.IsGitignore()) + sources, err := Globs(t.Dir, t.Sources, t.ShouldUseGitignore()) if err != nil { return "", err } diff --git a/internal/fingerprint/sources_timestamp.go b/internal/fingerprint/sources_timestamp.go index 5d48285193..929b044bca 100644 --- a/internal/fingerprint/sources_timestamp.go +++ b/internal/fingerprint/sources_timestamp.go @@ -28,7 +28,7 @@ func (checker *TimestampChecker) IsUpToDate(t *ast.Task) (bool, error) { return false, nil } - sources, err := Globs(t.Dir, t.Sources, t.IsGitignore()) + sources, err := Globs(t.Dir, t.Sources, t.ShouldUseGitignore()) if err != nil { return false, nil } @@ -54,7 +54,7 @@ func (checker *TimestampChecker) IsUpToDate(t *ast.Task) (bool, error) { } } - generates, err := Globs(t.Dir, t.Generates, t.IsGitignore()) + generates, err := Globs(t.Dir, t.Generates, t.ShouldUseGitignore()) if err != nil { return false, nil } @@ -112,7 +112,7 @@ func (checker *TimestampChecker) Kind() string { // Value implements the Checker Interface func (checker *TimestampChecker) Value(t *ast.Task) (any, error) { - sources, err := Globs(t.Dir, t.Sources, t.IsGitignore()) + sources, err := Globs(t.Dir, t.Sources, t.ShouldUseGitignore()) if err != nil { return time.Now(), err } diff --git a/taskfile/ast/task.go b/taskfile/ast/task.go index f7f0f31870..bff0ff596d 100644 --- a/taskfile/ast/task.go +++ b/taskfile/ast/task.go @@ -38,7 +38,7 @@ type Task struct { Method string Prefix string `hash:"ignore"` IgnoreError bool - Gitignore *bool + UseGitignore *bool Run string Platforms []*Platform If string @@ -76,10 +76,10 @@ func (t *Task) IsSilent() bool { return t.Silent != nil && *t.Silent } -// IsGitignore returns true if the task has gitignore filtering explicitly enabled. -// Returns false if Gitignore is nil (not set) or explicitly set to false. -func (t *Task) IsGitignore() bool { - return t.Gitignore != nil && *t.Gitignore +// ShouldUseGitignore returns true if the task has gitignore filtering explicitly enabled. +// Returns false if UseGitignore is nil (not set) or explicitly set to false. +func (t *Task) ShouldUseGitignore() bool { + return t.UseGitignore != nil && *t.UseGitignore } // WildcardMatch will check if the given string matches the name of the Task and returns any wildcard values. @@ -157,7 +157,7 @@ func (t *Task) UnmarshalYAML(node *yaml.Node) error { Method string Prefix string IgnoreError bool `yaml:"ignore_error"` - Gitignore *bool `yaml:"gitignore,omitempty"` + UseGitignore *bool `yaml:"use_gitignore,omitempty"` Run string Platforms []*Platform If string @@ -198,7 +198,7 @@ func (t *Task) UnmarshalYAML(node *yaml.Node) error { t.Method = task.Method t.Prefix = task.Prefix t.IgnoreError = task.IgnoreError - t.Gitignore = deepcopy.Scalar(task.Gitignore) + t.UseGitignore = deepcopy.Scalar(task.UseGitignore) t.Run = task.Run t.Platforms = task.Platforms t.If = task.If @@ -242,7 +242,7 @@ func (t *Task) DeepCopy() *Task { Method: t.Method, Prefix: t.Prefix, IgnoreError: t.IgnoreError, - Gitignore: deepcopy.Scalar(t.Gitignore), + UseGitignore: deepcopy.Scalar(t.UseGitignore), Run: t.Run, IncludeVars: t.IncludeVars.DeepCopy(), IncludedTaskfileVars: t.IncludedTaskfileVars.DeepCopy(), diff --git a/taskfile/ast/taskfile.go b/taskfile/ast/taskfile.go index 125b2670e0..30dcbc8a07 100644 --- a/taskfile/ast/taskfile.go +++ b/taskfile/ast/taskfile.go @@ -34,7 +34,7 @@ type Taskfile struct { Dotenv []string Run string Interval time.Duration - Gitignore bool + UseGitignore bool `yaml:"use_gitignore"` } // Merge merges the second Taskfile into the first @@ -90,7 +90,7 @@ func (tf *Taskfile) UnmarshalYAML(node *yaml.Node) error { Dotenv []string Run string Interval time.Duration - Gitignore bool + UseGitignore bool `yaml:"use_gitignore"` } if err := node.Decode(&taskfile); err != nil { return errors.NewTaskfileDecodeError(err, node) @@ -108,7 +108,7 @@ func (tf *Taskfile) UnmarshalYAML(node *yaml.Node) error { tf.Dotenv = taskfile.Dotenv tf.Run = taskfile.Run tf.Interval = taskfile.Interval - tf.Gitignore = taskfile.Gitignore + tf.UseGitignore = taskfile.UseGitignore if tf.Includes == nil { tf.Includes = NewIncludes() } diff --git a/testdata/gitignore/Taskfile.yml b/testdata/gitignore/Taskfile.yml index c78e5a0efb..93452867c6 100644 --- a/testdata/gitignore/Taskfile.yml +++ b/testdata/gitignore/Taskfile.yml @@ -1,6 +1,6 @@ version: '3' -gitignore: true +use_gitignore: true tasks: build: @@ -13,8 +13,8 @@ tasks: - ./generated.txt method: checksum - build-no-gitignore: - gitignore: false + build-no-use_gitignore: + use_gitignore: false cmds: - cp ./source.txt ./generated.txt sources: diff --git a/variables.go b/variables.go index 18d716a548..2fbe1f9bb3 100644 --- a/variables.go +++ b/variables.go @@ -59,7 +59,7 @@ func (e *Executor) CompiledTaskForTaskList(call *Call) (*ast.Task, error) { Env: nil, Dotenv: origTask.Dotenv, Silent: deepcopy.Scalar(origTask.Silent), - Gitignore: deepcopy.Scalar(origTask.Gitignore), + UseGitignore: deepcopy.Scalar(origTask.UseGitignore), Interactive: origTask.Interactive, Internal: origTask.Internal, Method: origTask.Method, @@ -111,9 +111,9 @@ func (e *Executor) compiledTask(call *Call, evaluateShVars bool) (*ast.Task, err } } - gitignore := origTask.IsGitignore() - if origTask.Gitignore == nil { - gitignore = e.Taskfile.Gitignore + gitignore := origTask.ShouldUseGitignore() + if origTask.UseGitignore == nil { + gitignore = e.Taskfile.UseGitignore } new := ast.Task{ @@ -132,7 +132,7 @@ func (e *Executor) compiledTask(call *Call, evaluateShVars bool) (*ast.Task, err Env: nil, Dotenv: templater.Replace(origTask.Dotenv, cache), Silent: deepcopy.Scalar(origTask.Silent), - Gitignore: &gitignore, + UseGitignore: &gitignore, Interactive: origTask.Interactive, Internal: origTask.Internal, Method: templater.Replace(origTask.Method, cache), diff --git a/watch.go b/watch.go index 349dd57a69..1a0dbee0c7 100644 --- a/watch.go +++ b/watch.go @@ -205,7 +205,7 @@ func (e *Executor) collectSources(calls []*Call) ([]string, error) { var sources []string err := e.traverse(calls, func(task *ast.Task) error { - files, err := fingerprint.Globs(task.Dir, task.Sources, task.IsGitignore()) + files, err := fingerprint.Globs(task.Dir, task.Sources, task.ShouldUseGitignore()) if err != nil { return err } diff --git a/website/src/public/schema.json b/website/src/public/schema.json index 37751fa4fe..61f7a843b7 100644 --- a/website/src/public/schema.json +++ b/website/src/public/schema.json @@ -177,7 +177,7 @@ "enum": ["none", "checksum", "timestamp"], "default": "none" }, - "gitignore": { + "use_gitignore": { "description": "When set to true, files matching .gitignore rules will be excluded from sources and generates glob resolution. Overrides the global gitignore setting.", "type": "boolean", "default": false @@ -692,7 +692,7 @@ "enum": ["none", "checksum", "timestamp"], "default": "checksum" }, - "gitignore": { + "use_gitignore": { "description": "When set to true, files matching .gitignore rules will be excluded from sources and generates glob resolution for all tasks. Can be overridden per task.", "type": "boolean", "default": false From fa03d6e5074c3f7e037804d931db1357ca13b269 Mon Sep 17 00:00:00 2001 From: Valentin Maerten Date: Sat, 4 Apr 2026 13:14:43 +0200 Subject: [PATCH 6/6] style: fix formatting --- taskfile/ast/task.go | 6 ++--- taskfile/ast/taskfile.go | 54 ++++++++++++++++++++-------------------- variables.go | 4 +-- 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/taskfile/ast/task.go b/taskfile/ast/task.go index bff0ff596d..c9d2c20779 100644 --- a/taskfile/ast/task.go +++ b/taskfile/ast/task.go @@ -38,7 +38,7 @@ type Task struct { Method string Prefix string `hash:"ignore"` IgnoreError bool - UseGitignore *bool + UseGitignore *bool Run string Platforms []*Platform If string @@ -157,7 +157,7 @@ func (t *Task) UnmarshalYAML(node *yaml.Node) error { Method string Prefix string IgnoreError bool `yaml:"ignore_error"` - UseGitignore *bool `yaml:"use_gitignore,omitempty"` + UseGitignore *bool `yaml:"use_gitignore,omitempty"` Run string Platforms []*Platform If string @@ -242,7 +242,7 @@ func (t *Task) DeepCopy() *Task { Method: t.Method, Prefix: t.Prefix, IgnoreError: t.IgnoreError, - UseGitignore: deepcopy.Scalar(t.UseGitignore), + UseGitignore: deepcopy.Scalar(t.UseGitignore), Run: t.Run, IncludeVars: t.IncludeVars.DeepCopy(), IncludedTaskfileVars: t.IncludedTaskfileVars.DeepCopy(), diff --git a/taskfile/ast/taskfile.go b/taskfile/ast/taskfile.go index 30dcbc8a07..9de0f90255 100644 --- a/taskfile/ast/taskfile.go +++ b/taskfile/ast/taskfile.go @@ -20,20 +20,20 @@ var ErrIncludedTaskfilesCantHaveDotenvs = errors.New("task: Included Taskfiles c // Taskfile is the abstract syntax tree for a Taskfile type Taskfile struct { - Location string - Version *semver.Version - Output Output - Method string - Includes *Includes - Set []string - Shopt []string - Vars *Vars - Env *Vars - Tasks *Tasks - Silent bool - Dotenv []string - Run string - Interval time.Duration + Location string + Version *semver.Version + Output Output + Method string + Includes *Includes + Set []string + Shopt []string + Vars *Vars + Env *Vars + Tasks *Tasks + Silent bool + Dotenv []string + Run string + Interval time.Duration UseGitignore bool `yaml:"use_gitignore"` } @@ -77,19 +77,19 @@ func (tf *Taskfile) UnmarshalYAML(node *yaml.Node) error { switch node.Kind { case yaml.MappingNode: var taskfile struct { - Version *semver.Version - Output Output - Method string - Includes *Includes - Set []string - Shopt []string - Vars *Vars - Env *Vars - Tasks *Tasks - Silent bool - Dotenv []string - Run string - Interval time.Duration + Version *semver.Version + Output Output + Method string + Includes *Includes + Set []string + Shopt []string + Vars *Vars + Env *Vars + Tasks *Tasks + Silent bool + Dotenv []string + Run string + Interval time.Duration UseGitignore bool `yaml:"use_gitignore"` } if err := node.Decode(&taskfile); err != nil { diff --git a/variables.go b/variables.go index 2fbe1f9bb3..dad3ca9219 100644 --- a/variables.go +++ b/variables.go @@ -59,7 +59,7 @@ func (e *Executor) CompiledTaskForTaskList(call *Call) (*ast.Task, error) { Env: nil, Dotenv: origTask.Dotenv, Silent: deepcopy.Scalar(origTask.Silent), - UseGitignore: deepcopy.Scalar(origTask.UseGitignore), + UseGitignore: deepcopy.Scalar(origTask.UseGitignore), Interactive: origTask.Interactive, Internal: origTask.Internal, Method: origTask.Method, @@ -132,7 +132,7 @@ func (e *Executor) compiledTask(call *Call, evaluateShVars bool) (*ast.Task, err Env: nil, Dotenv: templater.Replace(origTask.Dotenv, cache), Silent: deepcopy.Scalar(origTask.Silent), - UseGitignore: &gitignore, + UseGitignore: &gitignore, Interactive: origTask.Interactive, Internal: origTask.Internal, Method: templater.Replace(origTask.Method, cache),