Skip to content

Commit 16b20e2

Browse files
committed
Swap over to yara-x; improve performance and readability
Signed-off-by: egibs <20933572+egibs@users.noreply.github.com>
1 parent fcd1105 commit 16b20e2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+2197
-1853
lines changed

.github/workflows/go-tests.yaml

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ permissions:
1717
jobs:
1818
test:
1919
runs-on: mal-ubuntu-latest-8-core
20-
20+
env:
21+
PKG_CONFIG_PATH: ${{ github.workspace }}
22+
LD_LIBRARY_PATH: ${{ github.workspace }}
2123
steps:
2224
- uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
2325
with:
@@ -35,8 +37,25 @@ jobs:
3537

3638
- name: install dependencies
3739
run: |
38-
sudo apt update && sudo apt install libyara-dev xz-utils -y
40+
sudo apt update && sudo apt install xz-utils -y
41+
42+
- name: Clone yara-x
43+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
44+
with:
45+
repository: VirusTotal/yara-x
46+
path: yara-x
3947

48+
- name: Setup Rust
49+
uses: dtolnay/rust-toolchain@315e265cd78dad1e1dcf3a5074f6d6c47029d5aa # ???
50+
with:
51+
toolchain: stable
52+
53+
- name: Install yara-x-capi
54+
run: |
55+
cd ${{ github.workspace }}/yara-x
56+
cargo install cargo-c
57+
cargo cinstall -p yara-x-capi --release --pkgconfigdir=${{ github.workspace }} --includedir=${{ github.workspace }} --libdir=${{ github.workspace }}
58+
cd ${{ github.workspace }}
4059
- name: Unit tests
4160
run: |
4261
make test

.github/workflows/style.yaml

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ jobs:
114114

115115
golangci-lint:
116116
name: golangci-lint
117-
runs-on: ubuntu-24.04
117+
runs-on: mal-ubuntu-latest-8-core
118118

119119
steps:
120120
- name: Harden Runner
@@ -130,13 +130,30 @@ jobs:
130130
go-version-file: go.mod
131131
check-latest: true
132132

133-
- name: install libyara-dev
134-
run: |
135-
sudo apt update && sudo apt install libyara-dev -y
133+
- name: Clone yara-x
134+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
135+
with:
136+
repository: VirusTotal/yara-x
137+
path: yara-x
136138

139+
- name: Setup Rust
140+
uses: dtolnay/rust-toolchain@315e265cd78dad1e1dcf3a5074f6d6c47029d5aa # ???
141+
with:
142+
toolchain: stable
143+
144+
- name: Install yara-x-capi
145+
run: |
146+
cd ${{ github.workspace }}/yara-x
147+
cargo install cargo-c
148+
cargo cinstall -p yara-x-capi --release --destdir /tmp/yara-x
149+
sudo mkdir -p /usr/local/lib
150+
sudo mkdir -p /usr/local/include
151+
sudo cp /tmp/yara-x/usr/local/include/yara_x.h /usr/local/include/
152+
sudo cp -a /tmp/yara-x/usr/local/lib/x86_64-linux-gnu/* /usr/local/lib/
153+
sudo ldconfig -v
154+
cd ${{ github.workspace }}
137155
- name: golangci-lint
138156
uses: golangci/golangci-lint-action@971e284b6050e8a5849b72094c50ab08da042db8 # v6.1.1
139157
with:
140158
version: v1.62.0
141159
args: --timeout=5m
142-

.github/workflows/third-party.yaml

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ jobs:
1212
update:
1313
if: ${{ github.repository }} == 'chainguard-dev/malcontent'
1414
runs-on: mal-ubuntu-latest-8-core
15+
env:
16+
PKG_CONFIG_PATH: ${{ github.workspace }}
17+
LD_LIBRARY_PATH: ${{ github.workspace }}
1518
permissions:
1619
contents: write
1720
id-token: write
@@ -28,9 +31,23 @@ jobs:
2831
with:
2932
scope: chainguard-dev/malcontent
3033
identity: third-party
31-
- name: Install yara and libyara-dev
34+
- name: Clone yara-x
35+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
36+
with:
37+
repository: VirusTotal/yara-x
38+
path: yara-x
39+
40+
- name: Setup Rust
41+
uses: dtolnay/rust-toolchain@315e265cd78dad1e1dcf3a5074f6d6c47029d5aa # ???
42+
with:
43+
toolchain: stable
44+
45+
- name: Install yara-x-capi
3246
run: |
33-
sudo apt update && sudo apt install yara libyara-dev -y
47+
cd ${{ github.workspace }}/yara-x
48+
cargo install cargo-c
49+
cargo cinstall -p yara-x-capi --release --pkgconfigdir=${{ github.workspace }} --includedir=${{ github.workspace }} --libdir=${{ github.workspace }}
50+
cd ${{ github.workspace }}
3451
- name: Run make update-third-party
3552
run: |
3653
make update-third-party

go.mod

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module github.com/chainguard-dev/malcontent
33
go 1.23.3
44

55
require (
6+
github.com/VirusTotal/yara-x/go v0.12.0
67
github.com/agext/levenshtein v1.2.3
78
github.com/cavaliergopher/cpio v1.0.1
89
github.com/cavaliergopher/rpm v1.2.0
@@ -15,13 +16,14 @@ require (
1516
github.com/gabriel-vasile/mimetype v1.4.7
1617
github.com/google/go-cmp v0.6.0
1718
github.com/google/go-containerregistry v0.20.2
18-
github.com/hillu/go-yara/v4 v4.3.3
19+
github.com/klauspost/compress v1.17.11
1920
github.com/olekukonko/tablewriter v0.0.5
2021
github.com/shirou/gopsutil/v4 v4.24.11
2122
github.com/ulikunitz/xz v0.5.12
2223
github.com/urfave/cli/v2 v2.27.5
2324
github.com/wk8/go-ordered-map/v2 v2.1.8
2425
golang.org/x/sync v0.10.0
26+
golang.org/x/sys v0.28.0
2527
golang.org/x/term v0.27.0
2628
gopkg.in/yaml.v3 v3.0.1
2729
)
@@ -30,21 +32,20 @@ require (
3032
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
3133
github.com/bahlo/generic-list-go v0.2.0 // indirect
3234
github.com/buger/jsonparser v1.1.1 // indirect
33-
github.com/charmbracelet/x/ansi v0.4.5 // indirect
35+
github.com/charmbracelet/x/ansi v0.6.0 // indirect
3436
github.com/charmbracelet/x/term v0.2.1 // indirect
35-
github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect
36-
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
37-
github.com/docker/cli v27.3.1+incompatible // indirect
37+
github.com/containerd/stargz-snapshotter/estargz v0.16.3 // indirect
38+
github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect
39+
github.com/docker/cli v27.4.1+incompatible // indirect
3840
github.com/docker/distribution v2.8.3+incompatible // indirect
3941
github.com/docker/docker-credential-helpers v0.8.2 // indirect
4042
github.com/ebitengine/purego v0.8.1 // indirect
4143
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
4244
github.com/go-ole/go-ole v1.3.0 // indirect
43-
github.com/klauspost/compress v1.17.11 // indirect
4445
github.com/kr/pretty v0.2.1 // indirect
4546
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
4647
github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 // indirect
47-
github.com/mailru/easyjson v0.7.7 // indirect
48+
github.com/mailru/easyjson v0.9.0 // indirect
4849
github.com/mattn/go-colorable v0.1.13 // indirect
4950
github.com/mattn/go-isatty v0.0.20 // indirect
5051
github.com/mattn/go-localereader v0.0.1 // indirect
@@ -66,8 +67,8 @@ require (
6667
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
6768
github.com/yusufpapurcu/wmi v1.2.4 // indirect
6869
golang.org/x/crypto v0.31.0 // indirect
69-
golang.org/x/net v0.31.0 // indirect
70-
golang.org/x/sys v0.28.0 // indirect
70+
golang.org/x/net v0.33.0 // indirect
7171
golang.org/x/text v0.21.0 // indirect
72+
google.golang.org/protobuf v1.36.0 // indirect
7273
pault.ag/go/topsort v0.1.1 // indirect
7374
)

go.sum

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
github.com/VirusTotal/yara-x/go v0.12.0 h1:nR7MKfNOOqsLXyeJYjgFOQcCjfME9qAoDLiN2Z7/pcg=
2+
github.com/VirusTotal/yara-x/go v0.12.0/go.mod h1:lgXP/nkYX349MVowrtTtU5hzMdCOWQLv3+wKll9+0F8=
13
github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo=
24
github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
35
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
@@ -18,19 +20,19 @@ github.com/charmbracelet/bubbletea v1.2.4 h1:KN8aCViA0eps9SCOThb2/XPIlea3ANJLUkv
1820
github.com/charmbracelet/bubbletea v1.2.4/go.mod h1:Qr6fVQw+wX7JkWWkVyXYk/ZUQ92a6XNekLXa3rR18MM=
1921
github.com/charmbracelet/lipgloss v1.0.0 h1:O7VkGDvqEdGi93X+DeqsQ7PKHDgtQfF8j8/O2qFMQNg=
2022
github.com/charmbracelet/lipgloss v1.0.0/go.mod h1:U5fy9Z+C38obMs+T+tJqst9VGzlOYGj4ri9reL3qUlo=
21-
github.com/charmbracelet/x/ansi v0.4.5 h1:LqK4vwBNaXw2AyGIICa5/29Sbdq58GbGdFngSexTdRM=
22-
github.com/charmbracelet/x/ansi v0.4.5/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw=
23+
github.com/charmbracelet/x/ansi v0.6.0 h1:qOznutrb93gx9oMiGf7caF7bqqubh6YIM0SWKyA08pA=
24+
github.com/charmbracelet/x/ansi v0.6.0/go.mod h1:KBUFw1la39nl0dLl10l5ORDAqGXaeurTQmwyyVKse/Q=
2325
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
2426
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
25-
github.com/containerd/stargz-snapshotter/estargz v0.15.1 h1:eXJjw9RbkLFgioVaTG+G/ZW/0kEe2oEKCdS/ZxIyoCU=
26-
github.com/containerd/stargz-snapshotter/estargz v0.15.1/go.mod h1:gr2RNwukQ/S9Nv33Lt6UC7xEx58C+LHRdoqbEKjz1Kk=
27-
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
28-
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
27+
github.com/containerd/stargz-snapshotter/estargz v0.16.3 h1:7evrXtoh1mSbGj/pfRccTampEyKpjpOnS3CyiV1Ebr8=
28+
github.com/containerd/stargz-snapshotter/estargz v0.16.3/go.mod h1:uyr4BfYfOj3G9WBVE8cOlQmXAbPN9VEQpBBeJIuOipU=
29+
github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0=
30+
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
2931
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3032
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
3133
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
32-
github.com/docker/cli v27.3.1+incompatible h1:qEGdFBF3Xu6SCvCYhc7CzaQTlBmqDuzxPDpigSyeKQQ=
33-
github.com/docker/cli v27.3.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
34+
github.com/docker/cli v27.4.1+incompatible h1:VzPiUlRJ/xh+otB75gva3r05isHMo5wXDfPRi5/b4hI=
35+
github.com/docker/cli v27.4.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
3436
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
3537
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
3638
github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo=
@@ -52,9 +54,6 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
5254
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
5355
github.com/google/go-containerregistry v0.20.2 h1:B1wPJ1SN/S7pB+ZAimcciVD+r+yV/l/DSArMxlbwseo=
5456
github.com/google/go-containerregistry v0.20.2/go.mod h1:z38EKdKh4h7IP2gSfUUqEvalZBqs6AoLeWfUy34nQC8=
55-
github.com/hillu/go-yara/v4 v4.3.3 h1:O+7iYTZK20fzsXiJyvA0d529RTdnZCrgS6HdE0O7BMg=
56-
github.com/hillu/go-yara/v4 v4.3.3/go.mod h1:AHEs/FXVMQKVVlT6iG9d+q1BRr0gq0WoAWZQaZ0gS7s=
57-
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
5857
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
5958
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
6059
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
@@ -66,8 +65,8 @@ github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69
6665
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
6766
github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 h1:7UMa6KCCMjZEMDtTVdcGu0B1GmmC7QJKiCCjyTAWQy0=
6867
github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k=
69-
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
70-
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
68+
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
69+
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
7170
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
7271
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
7372
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
@@ -129,8 +128,8 @@ github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo
129128
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
130129
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
131130
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
132-
golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
133-
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
131+
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
132+
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
134133
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
135134
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
136135
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -146,6 +145,8 @@ golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
146145
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
147146
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
148147
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
148+
google.golang.org/protobuf v1.36.0 h1:mjIs9gYtt56AzC4ZaffQuh88TZurBGhIJMBZGSxNerQ=
149+
google.golang.org/protobuf v1.36.0/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
149150
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
150151
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
151152
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=

pkg/action/path.go

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
package action
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"os"
7+
"path/filepath"
8+
"strings"
9+
"sync"
10+
11+
"github.com/chainguard-dev/clog"
12+
)
13+
14+
// findFilesRecursively returns a list of files found recursively within a path.
15+
func findFilesRecursively(ctx context.Context, rootPath string) ([]string, error) {
16+
logger := clog.FromContext(ctx)
17+
var files []string
18+
var mu sync.Mutex
19+
var wg sync.WaitGroup
20+
21+
root, err := filepath.EvalSymlinks(rootPath)
22+
if err != nil {
23+
// If the target does not exist, log the error but return gracefully
24+
if os.IsNotExist(err) {
25+
logger.Debugf("symlink target does not exist: %s", err.Error())
26+
return nil, nil
27+
}
28+
// Allow /proc/XXX/exe to be scanned even if symlink is not resolveable
29+
if strings.HasPrefix(rootPath, "/proc/") {
30+
root = rootPath
31+
} else {
32+
return nil, fmt.Errorf("eval %q: %w", rootPath, err)
33+
}
34+
}
35+
36+
var processPath func(string) error
37+
processPath = func(path string) error {
38+
defer wg.Done()
39+
40+
select {
41+
case <-ctx.Done():
42+
return ctx.Err()
43+
default:
44+
}
45+
46+
info, err := os.Lstat(path)
47+
if err != nil {
48+
logger.Errorf("error reading path %s: %v", path, err)
49+
return nil
50+
}
51+
52+
if info.Mode()&os.ModeSymlink != 0 {
53+
realPath, err := filepath.EvalSymlinks(path)
54+
if err != nil {
55+
logger.Errorf("error resolving symlink %s: %v", path, err)
56+
return nil
57+
}
58+
info, err = os.Lstat(realPath)
59+
if err != nil {
60+
logger.Errorf("error reading resolved path %s: %v", realPath, err)
61+
return nil
62+
}
63+
path = realPath
64+
}
65+
66+
if info.IsDir() {
67+
// Skip .git directories
68+
if strings.Contains(path, "/.git/") {
69+
return nil
70+
}
71+
72+
entries, err := os.ReadDir(path)
73+
if err != nil {
74+
logger.Errorf("error reading directory %s: %v", path, err)
75+
return nil
76+
}
77+
78+
for _, entry := range entries {
79+
subPath := filepath.Join(path, entry.Name())
80+
wg.Add(1)
81+
go func(p string) {
82+
if err := processPath(p); err != nil {
83+
logger.Errorf("error processing path %s: %v", p, err)
84+
}
85+
}(subPath)
86+
}
87+
return nil
88+
}
89+
90+
mu.Lock()
91+
defer mu.Unlock()
92+
files = append(files, path)
93+
return nil
94+
}
95+
96+
wg.Add(1)
97+
if err := processPath(root); err != nil {
98+
return nil, fmt.Errorf("process root path: %w", err)
99+
}
100+
101+
wg.Wait()
102+
103+
return files, nil
104+
}
105+
106+
// cleanPath removes the temporary directory prefix from the path.
107+
func cleanPath(path string, prefix string) (string, error) {
108+
pathEval, err := filepath.EvalSymlinks(path)
109+
if err != nil {
110+
return "", err
111+
}
112+
prefixEval, err := filepath.EvalSymlinks(prefix)
113+
if err != nil {
114+
return "", err
115+
}
116+
return strings.TrimPrefix(pathEval, prefixEval), nil
117+
}
118+
119+
// formatPath formats the path for display.
120+
func formatPath(path string) string {
121+
if strings.Contains(path, "\\") {
122+
path = strings.ReplaceAll(path, "\\", "/")
123+
}
124+
return path
125+
}

0 commit comments

Comments
 (0)