diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 3fb2754f..dc10bd37 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -15,7 +15,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v4 with: - go-version: 1.21.x + go-version: 1.24.x - name: Check out code uses: actions/checkout@v3 diff --git a/.github/workflows/changelog-update.yml b/.github/workflows/changelog-update.yml index ad715649..7b53a915 100644 --- a/.github/workflows/changelog-update.yml +++ b/.github/workflows/changelog-update.yml @@ -13,7 +13,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v4 with: - go-version: 1.21.x + go-version: 1.24.x - name: Checkout code uses: actions/checkout@v3 diff --git a/.github/workflows/lint-test.yml b/.github/workflows/lint-test.yml index ac6b5e2d..c562c501 100644 --- a/.github/workflows/lint-test.yml +++ b/.github/workflows/lint-test.yml @@ -15,7 +15,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v4 with: - go-version: 1.21.x + go-version: 1.24.x - name: Run golangci-lint uses: golangci/golangci-lint-action@v3.7.0 with: diff --git a/auth/pdcp/auth.go b/auth/pdcp/auth.go index 3dee583e..7588ebc8 100644 --- a/auth/pdcp/auth.go +++ b/auth/pdcp/auth.go @@ -96,6 +96,8 @@ func readPasswordFromUnix() ([]byte, error) { if err != nil { return nil, err } - defer tty.Close() + defer func() { + _ = tty.Close() + }() return term.ReadPassword(int(tty.Fd())) } diff --git a/auth/pdcp/creds.go b/auth/pdcp/creds.go index 94a80ff1..3e719bca 100644 --- a/auth/pdcp/creds.go +++ b/auth/pdcp/creds.go @@ -120,7 +120,9 @@ func (p *PDCPCredHandler) ValidateAPIKey(key string, host string, toolName strin _ = resp.Body.Close() return nil, fmt.Errorf("invalid status code: %d", resp.StatusCode) } - defer resp.Body.Close() + defer func() { + _ = resp.Body.Close() + }() bin, err := io.ReadAll(resp.Body) if err != nil { return nil, err diff --git a/auth/pdcp/creds_test.go b/auth/pdcp/creds_test.go index cc38a7c6..1f0f8ae7 100644 --- a/auth/pdcp/creds_test.go +++ b/auth/pdcp/creds_test.go @@ -21,7 +21,9 @@ func TestLoadCreds(t *testing.T) { f, err := os.CreateTemp("", "creds-test-*") require.Nil(t, err) _, _ = f.WriteString(strings.TrimSpace(exampleCred)) - defer os.Remove(f.Name()) + defer func() { + _ = os.Remove(f.Name()) + }() PDCPCredFile = f.Name() PDCPDir = filepath.Dir(f.Name()) h := &PDCPCredHandler{} diff --git a/buffer/disk.go b/buffer/disk.go index 708ab843..043d3ea2 100644 --- a/buffer/disk.go +++ b/buffer/disk.go @@ -47,6 +47,6 @@ func (db *DiskBuffer) Reader() (io.ReadSeekCloser, error) { func (db *DiskBuffer) Close() { name := db.f.Name() - db.f.Close() - os.RemoveAll(name) + _ = db.f.Close() + _ = os.RemoveAll(name) } diff --git a/env/env_test.go b/env/env_test.go index dbc31c53..6b31f259 100644 --- a/env/env_test.go +++ b/env/env_test.go @@ -9,8 +9,10 @@ import ( func TestExpandWithEnv(t *testing.T) { testEnvVar := "TEST_VAR" testEnvValue := "TestValue" - os.Setenv(testEnvVar, testEnvValue) - defer os.Unsetenv(testEnvVar) + _ = os.Setenv(testEnvVar, testEnvValue) + defer func() { + _ = os.Unsetenv(testEnvVar) + }() tests := []struct { input string @@ -46,35 +48,35 @@ func TestExpandWithEnvNilInput(t *testing.T) { func TestGetEnvOrDefault(t *testing.T) { // Test for string - os.Setenv("TEST_STRING", "test") + _ = os.Setenv("TEST_STRING", "test") resultString := GetEnvOrDefault("TEST_STRING", "default") if resultString != "test" { t.Errorf("Expected 'test', got %s", resultString) } // Test for int - os.Setenv("TEST_INT", "123") + _ = os.Setenv("TEST_INT", "123") resultInt := GetEnvOrDefault("TEST_INT", 0) if resultInt != 123 { t.Errorf("Expected 123, got %d", resultInt) } // Test for bool - os.Setenv("TEST_BOOL", "true") + _ = os.Setenv("TEST_BOOL", "true") resultBool := GetEnvOrDefault("TEST_BOOL", false) if resultBool != true { t.Errorf("Expected true, got %t", resultBool) } // Test for float64 - os.Setenv("TEST_FLOAT", "1.23") + _ = os.Setenv("TEST_FLOAT", "1.23") resultFloat := GetEnvOrDefault("TEST_FLOAT", 0.0) if resultFloat != 1.23 { t.Errorf("Expected 1.23, got %f", resultFloat) } // Test for time.Duration - os.Setenv("TEST_DURATION", "1h") + _ = os.Setenv("TEST_DURATION", "1h") resultDuration := GetEnvOrDefault("TEST_DURATION", time.Duration(0)) if resultDuration != time.Hour { t.Errorf("Expected 1h, got %s", resultDuration) diff --git a/errkit/errors.go b/errkit/errors.go index 480fae3e..728fcab5 100644 --- a/errkit/errors.go +++ b/errkit/errors.go @@ -375,7 +375,7 @@ func parseError(to *ErrorX, err error) { } case CauseError: to.append(v.Cause()) - remaining := strings.Replace(err.Error(), v.Cause().Error(), "", -1) + remaining := strings.ReplaceAll(err.Error(), v.Cause().Error(), "") parseError(to, errors.New(remaining)) default: errString := err.Error() diff --git a/exec/executil.go b/exec/executil.go index 867c18fb..16ff81c5 100644 --- a/exec/executil.go +++ b/exec/executil.go @@ -157,9 +157,11 @@ func RunSafe(cmd ...string) (string, error) { return "", errkit.WithMessage(err, "failed to create stdout pipe") } - defer in.Close() - defer errorOut.Close() - defer out.Close() + defer func() { + _ = in.Close() + _ = errorOut.Close() + _ = out.Close() + }() if err := cmdExec.Start(); err != nil { return "", errkit.Wrap(err, "failed to start command") @@ -199,9 +201,11 @@ func RunSh(cmd ...string) (string, error) { return "", errkit.WithMessage(err, "failed to create stdout pipe") } - defer in.Close() - defer errorOut.Close() - defer out.Close() + defer func() { + _ = in.Close() + _ = errorOut.Close() + _ = out.Close() + }() if err := cmdExec.Start(); err != nil { errorData, _ := io.ReadAll(errorOut) @@ -257,9 +261,11 @@ func RunPS(cmd string) (string, error) { return "", errkit.WithMessage(err, "failed to create stdout pipe") } - defer in.Close() - defer errorOut.Close() - defer out.Close() + defer func() { + _ = in.Close() + _ = errorOut.Close() + _ = out.Close() + }() if err := cmdExec.Start(); err != nil { return "", errkit.WithMessage(err, "start powershell.exe process error") diff --git a/file/clean_test.go b/file/clean_test.go index ca3102b0..319ca743 100644 --- a/file/clean_test.go +++ b/file/clean_test.go @@ -51,7 +51,9 @@ func FuzzSafeOpen(f *testing.F) { // Ignore errors return } - defer result.Close() + defer func() { + _ = result.Close() + }() bin, _ := io.ReadAll(result) if string(bin) == "pwned!" { t.Fatalf("pwned! cleaned=%s ,input=%s", cleaned, fuzzPath) diff --git a/file/file.go b/file/file.go index 74956a6a..1160e9f5 100644 --- a/file/file.go +++ b/file/file.go @@ -134,7 +134,7 @@ func DeleteFilesOlderThan(folder string, filter FileFilters) error { if filter.Callback != nil { return filter.Callback(osPathname) } else { - os.RemoveAll(osPathname) + _ = os.RemoveAll(osPathname) } } return nil @@ -152,12 +152,16 @@ func DownloadFile(filepath string, url string) error { if err != nil { return err } - defer resp.Body.Close() + defer func() { + _ = resp.Body.Close() + }() out, err := os.Create(filepath) if err != nil { return err } - defer out.Close() + defer func() { + _ = out.Close() + }() _, err = io.Copy(out, resp.Body) return err } @@ -238,7 +242,9 @@ func ReadFile(filename string) (chan string, error) { if err != nil { return } - defer f.Close() + defer func() { + _ = f.Close() + }() scanner := bufio.NewScanner(f) for scanner.Scan() { out <- scanner.Text() @@ -260,7 +266,9 @@ func ReadFileWithBufferSize(filename string, maxCapacity int) (chan string, erro if err != nil { return } - defer f.Close() + defer func() { + _ = f.Close() + }() scanner := bufio.NewScanner(f) buf := make([]byte, maxCapacity) scanner.Buffer(buf, maxCapacity) @@ -295,13 +303,17 @@ func CopyFile(src, dst string) error { if err != nil { return err } - defer srcFile.Close() + defer func() { + _ = srcFile.Close() + }() dstFile, err := os.Create(dst) if err != nil { return err } - defer dstFile.Close() + defer func() { + _ = dstFile.Close() + }() _, err = io.Copy(dstFile, srcFile) if err != nil { @@ -325,7 +337,9 @@ func Unmarshal(encodeType EncodeType, data []byte, obj interface{}) error { if err != nil { return err } - defer dataFile.Close() + defer func() { + _ = dataFile.Close() + }() return UnmarshalFromReader(encodeType, dataFile, obj) default: return UnmarshalFromReader(encodeType, bytes.NewReader(data), obj) @@ -351,7 +365,9 @@ func Marshal(encodeType EncodeType, data []byte, obj interface{}) error { if err != nil { return err } - defer dataFile.Close() + defer func() { + _ = dataFile.Close() + }() return MarshalToWriter(encodeType, dataFile, obj) default: return MarshalToWriter(encodeType, bytes.NewBuffer(data), obj) @@ -395,7 +411,9 @@ func UseMusl(path string) (bool, error) { if err != nil { return false, err } - defer file.Close() + defer func() { + _ = file.Close() + }() elfFile, err := elf.NewFile(file) if err != nil { return false, err @@ -431,7 +449,7 @@ func HasPermission(fileName string, permission int) (bool, error) { } return false, err } - file.Close() + _ = file.Close() return true, nil } @@ -454,7 +472,9 @@ func CountLinesWithSeparator(separator []byte, filename string) (uint, error) { return 0, err } - defer file.Close() + defer func() { + _ = file.Close() + }() if len(separator) == 0 { return 0, ErrInvalidSeparator } @@ -579,7 +599,9 @@ func DedupeLines(filename string) error { if err != nil { return errors.Wrapf(err, "could not open file: %s", filename) } - defer file.Close() + defer func() { + _ = file.Close() + }() seenLines := make(map[string]struct{}) var deduplicatedLines []string @@ -622,7 +644,9 @@ func IsEmpty(filename string) (bool, error) { if err != nil { return false, err } - defer file.Close() + defer func() { + _ = file.Close() + }() // Read up to 512 bytes to check for non-space characters buffer := make([]byte, 16) diff --git a/file/file_test.go b/file/file_test.go index 9d0ae555..fea38200 100644 --- a/file/file_test.go +++ b/file/file_test.go @@ -60,7 +60,9 @@ func TestDeleteFilesOlderThan(t *testing.T) { sleepTime := time.Duration(3 * time.Second) // defer temporary folder removal - defer os.RemoveAll(fo) + defer func() { + _ = os.RemoveAll(fo) + }() checkFolderErr := func(err error) { require.Nil(t, err, "couldn't create folder: %s", err) } @@ -71,7 +73,7 @@ func TestDeleteFilesOlderThan(t *testing.T) { fi, err := os.CreateTemp(fo, "") require.Nil(t, err, "couldn't create f: %s", err) fName := fi.Name() - fi.Close() + _ = fi.Close() return fName } t.Run("prefix props test", func(t *testing.T) { @@ -181,7 +183,7 @@ func TestDownloadFile(t *testing.T) { require.Nil(t, err, "couldn't create folder: %s", err) fname := tmpfile.Name() - os.Remove(fname) + _ = os.Remove(fname) err = DownloadFile(fname, "http://ipv4.download.thinkbroadband.com/5MB.zip") require.Nil(t, err, "couldn't download file: %s", err) @@ -189,7 +191,7 @@ func TestDownloadFile(t *testing.T) { require.True(t, FileExists(fname), "file \"%s\" doesn't exists", fname) // remove the downloaded file - os.Remove(fname) + _ = os.Remove(fname) } func tmpFolderName(s string) string { @@ -211,7 +213,7 @@ func TestCreateFolders(t *testing.T) { // remove folders for _, folder := range tests { - os.Remove(folder) + _ = os.Remove(folder) } } @@ -223,7 +225,7 @@ func TestCreateFolder(t *testing.T) { fexists := FolderExists(tst) require.True(t, fexists, "folder %s doesn't exist", fexists) - os.Remove(tst) + _ = os.Remove(tst) } func TestHasStdin(t *testing.T) { @@ -238,8 +240,10 @@ func TestReadFile(t *testing.T) { require.Nil(t, err, "couldn't create file: %s", err) fname := f.Name() _, _ = f.Write([]byte(fileContent)) - f.Close() - defer os.Remove(fname) + _ = f.Close() + defer func() { + _ = os.Remove(fname) + }() fileContentLines := strings.Split(fileContent, "\n") // compare file lines @@ -260,8 +264,10 @@ func TestReadFileWithBufferSize(t *testing.T) { require.Nil(t, err, "couldn't create file: %s", err) fname := f.Name() _, _ = f.Write([]byte(fileContent)) - f.Close() - defer os.Remove(fname) + _ = f.Close() + defer func() { + _ = os.Remove(fname) + }() fileContentLines := strings.Split(fileContent, "\n") // compare file lines @@ -278,8 +284,10 @@ func TestPermissions(t *testing.T) { f, err := os.CreateTemp("", "") require.Nil(t, err, "couldn't create file: %s", err) fname := f.Name() - f.Close() - defer os.Remove(fname) + _ = f.Close() + defer func() { + _ = os.Remove(fname) + }() ok, err := IsReadable(fname) require.True(t, ok) @@ -309,8 +317,10 @@ func TestReadFileWithReader(t *testing.T) { require.Nil(t, err, "couldn't create file: %s", err) fname := f.Name() _, _ = f.Write([]byte(fileContent)) - f.Close() - defer os.Remove(fname) + _ = f.Close() + defer func() { + _ = os.Remove(fname) + }() fileContentLines := strings.Split(fileContent, "\n") f, err = os.Open(fname) require.Nil(t, err, "couldn't create file: %s", err) @@ -321,7 +331,7 @@ func TestReadFileWithReader(t *testing.T) { require.Equal(t, fileContentLines[i], line, "lines don't match") i++ } - f.Close() + _ = f.Close() } func TestReadFileWithReaderAndBufferSize(t *testing.T) { @@ -332,8 +342,10 @@ func TestReadFileWithReaderAndBufferSize(t *testing.T) { require.Nil(t, err, "couldn't create file: %s", err) fname := f.Name() _, _ = f.Write([]byte(fileContent)) - f.Close() - defer os.Remove(fname) + _ = f.Close() + defer func() { + _ = os.Remove(fname) + }() fileContentLines := strings.Split(fileContent, "\n") f, err = os.Open(fname) require.Nil(t, err, "couldn't create file: %s", err) @@ -344,7 +356,7 @@ func TestReadFileWithReaderAndBufferSize(t *testing.T) { require.Equal(t, fileContentLines[i], line, "lines don't match") i++ } - f.Close() + _ = f.Close() } func TestCopyFile(t *testing.T) { @@ -355,18 +367,22 @@ func TestCopyFile(t *testing.T) { require.Nil(t, err, "couldn't create file: %s", err) fname := f.Name() _, _ = f.Write([]byte(fileContent)) - f.Close() - defer os.Remove(fname) + _ = f.Close() + defer func() { + _ = os.Remove(fname) + }() fnameCopy := fmt.Sprintf("%s-copy", f.Name()) err = CopyFile(fname, fnameCopy) require.Nil(t, err, "couldn't copy file: %s", err) require.True(t, FileExists(fnameCopy), "file \"%s\" doesn't exists", fnameCopy) - os.Remove(fnameCopy) + _ = os.Remove(fnameCopy) } func TestGetTempFileName(t *testing.T) { fname, _ := GetTempFileName() - defer os.Remove(fname) + defer func() { + _ = os.Remove(fname) + }() require.NotEmpty(t, fname) } @@ -426,7 +442,7 @@ func TestRemoveAll(t *testing.T) { require.Nil(t, err, "couldn't create folder: %s", err) f, err := os.CreateTemp(tmpdir, "") require.Nil(t, err, "couldn't create file: %s", err) - f.Close() + _ = f.Close() errs := RemoveAll(tmpdir) require.Equal(t, 0, len(errs), "couldn't remove folder: %s", errs) } @@ -494,13 +510,15 @@ func TestSubstituteConfigFromEnvVars(t *testing.T) { require.Nil(t, err, "couldn't create file: %s", err) fname := f.Name() _, _ = f.Write([]byte(configFileContent)) - f.Close() - defer os.Remove(fname) + _ = f.Close() + defer func() { + _ = os.Remove(fname) + }() - os.Setenv("CHANNEL", "test_channel") - os.Setenv("USER", "test_user") - os.Setenv("WEBHOOK", "test_webhook") - os.Setenv("THREADS", "test_threads") + _ = os.Setenv("CHANNEL", "test_channel") + _ = os.Setenv("USER", "test_user") + _ = os.Setenv("WEBHOOK", "test_webhook") + _ = os.Setenv("THREADS", "test_threads") expectedFileContent := `test: - id: some_id @@ -548,12 +566,12 @@ func TestOpenOrCreateFile(t *testing.T) { if err != nil { t.Fatalf("failed to create test file: %v", err) } - file.Close() + _ = file.Close() file, err = OpenOrCreateFile(testFileName) require.NoError(t, err) require.True(t, FileExists(testFileName)) - file.Close() + _ = file.Close() err = os.RemoveAll(testFileName) if err != nil { @@ -566,7 +584,7 @@ func TestOpenOrCreateFile(t *testing.T) { file, err := OpenOrCreateFile(testFileName) require.NoError(t, err) require.True(t, FileExists(testFileName)) - file.Close() + _ = file.Close() err = os.RemoveAll(testFileName) if err != nil { @@ -590,7 +608,9 @@ func TestFileExistsIn(t *testing.T) { if err != nil { t.Fatalf("failed to write to temporary file: %v", err) } - defer os.RemoveAll(tempFile) + defer func() { + _ = os.RemoveAll(tempFile) + }() tests := []struct { name string @@ -650,7 +670,9 @@ func TestIsEmpty(t *testing.T) { emptyFile := filepath.Join(tempDir, "empty.txt") err := os.WriteFile(emptyFile, []byte(""), 0644) require.NoError(t, err, "failed to create empty file") - defer os.Remove(emptyFile) // Clean up the created file + defer func() { + _ = os.Remove(emptyFile) + }() isEmpty, err := IsEmpty(emptyFile) require.NoError(t, err, "should not error for an empty file") require.True(t, isEmpty, "empty file should be considered empty") @@ -661,7 +683,9 @@ func TestIsEmpty(t *testing.T) { spacesFile := filepath.Join(tempDir, "spaces.txt") err := os.WriteFile(spacesFile, []byte(" "), 0644) require.NoError(t, err, "failed to create file with spaces") - defer os.Remove(spacesFile) // Clean up the created file + defer func() { + _ = os.Remove(spacesFile) + }() isEmpty, err := IsEmpty(spacesFile) require.NoError(t, err, "should not error for a file with only spaces") require.True(t, isEmpty, "file with only spaces should be considered empty") diff --git a/folder/folderutil_test.go b/folder/folderutil_test.go index b94f8a10..dd305b7e 100644 --- a/folder/folderutil_test.go +++ b/folder/folderutil_test.go @@ -35,7 +35,9 @@ func TestSyncDirectory(t *testing.T) { // setup // some files in a temp dir sourceDir := t.TempDir() - defer os.RemoveAll(sourceDir) + defer func() { + _ = os.RemoveAll(sourceDir) + }() _ = os.WriteFile(filepath.Join(sourceDir, "/file1.txt"), []byte("file1"), os.ModePerm) _ = os.WriteFile(filepath.Join(sourceDir, "/file2.txt"), []byte("file2"), os.ModePerm) @@ -53,7 +55,9 @@ func TestSyncDirectory(t *testing.T) { // setup // some files in a temp dir sourceDir := t.TempDir() - defer os.RemoveAll(sourceDir) + defer func() { + _ = os.RemoveAll(sourceDir) + }() _ = os.WriteFile(filepath.Join(sourceDir, "/file1.txt"), []byte("file1"), os.ModePerm) _ = os.WriteFile(filepath.Join(sourceDir, "/file2.txt"), []byte("file2"), os.ModePerm) _ = os.Mkdir(filepath.Join(sourceDir, "/dir1"), os.ModePerm) @@ -62,7 +66,9 @@ func TestSyncDirectory(t *testing.T) { // destination directory destinationDir := t.TempDir() - defer os.RemoveAll(destinationDir) + defer func() { + _ = os.RemoveAll(destinationDir) + }() // when: try to migrate files err := SyncDirectory(sourceDir, destinationDir) @@ -84,7 +90,9 @@ func TestSyncDirectory(t *testing.T) { // setup // some files in a temp dir sourceDir := t.TempDir() - defer os.RemoveAll(sourceDir) + defer func() { + _ = os.RemoveAll(sourceDir) + }() _ = os.WriteFile(filepath.Join(sourceDir, "/file1.txt"), []byte("file1"), os.ModePerm) _ = os.WriteFile(filepath.Join(sourceDir, "/file2.txt"), []byte("file2"), os.ModePerm) _ = os.Mkdir(filepath.Join(sourceDir, "/dir1"), os.ModePerm) @@ -93,7 +101,9 @@ func TestSyncDirectory(t *testing.T) { // destination directory destinationDir := t.TempDir() - defer os.RemoveAll(destinationDir) + defer func() { + _ = os.RemoveAll(destinationDir) + }() // when: try to migrate files RemoveSourceDirAfterSync = false @@ -117,7 +127,9 @@ func TestIsWritable(t *testing.T) { t.Run("Test writable directory", func(t *testing.T) { tempDir, err := os.MkdirTemp("", "test-dir") assert.NoError(t, err) - defer os.RemoveAll(tempDir) + defer func() { + _ = os.RemoveAll(tempDir) + }() assert.True(t, IsWritable(tempDir), "expected directory to be writable") }) @@ -137,7 +149,9 @@ func TestIsWritable(t *testing.T) { nonWritableDir := "non-writable-dir" err := os.Mkdir(nonWritableDir, 0400) assert.NoError(t, err) - defer os.RemoveAll(nonWritableDir) + defer func() { + _ = os.RemoveAll(nonWritableDir) + }() // Make the directory non-writable. err = os.Chmod(nonWritableDir, 0400) @@ -149,7 +163,9 @@ func TestIsWritable(t *testing.T) { t.Run("Test with a file instead of a directory", func(t *testing.T) { tempFile, err := os.CreateTemp("", "test-file") assert.NoError(t, err) - defer os.Remove(tempFile.Name()) + defer func() { + _ = os.Remove(tempFile.Name()) + }() assert.False(t, IsWritable(tempFile.Name()), "expected file to not be considered a writable directory") }) diff --git a/go.mod b/go.mod index fda89450..77fff6c0 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 github.com/cespare/xxhash v1.1.0 github.com/charmbracelet/glamour v0.8.0 + github.com/dlclark/regexp2 v1.11.5 github.com/docker/go-units v0.5.0 github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 github.com/felixge/fgprof v0.9.5 @@ -33,6 +34,7 @@ require ( github.com/shirou/gopsutil/v3 v3.23.7 github.com/stretchr/testify v1.10.0 github.com/tidwall/gjson v1.18.0 + github.com/wasilibs/go-re2 v1.10.0 github.com/zmap/zcrypto v0.0.0-20230422215203-9a665e1e9968 go.uber.org/multierr v1.11.0 golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 @@ -58,7 +60,6 @@ require ( github.com/charmbracelet/x/ansi v0.3.2 // indirect github.com/cloudflare/circl v1.6.1 // indirect github.com/dimchansky/utfbom v1.1.1 // indirect - github.com/dlclark/regexp2 v1.11.4 // indirect github.com/fatih/color v1.15.0 // indirect github.com/gaissmai/bart v0.20.4 // indirect github.com/go-ole/go-ole v1.2.6 // indirect @@ -90,6 +91,7 @@ require ( github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/sorairolake/lzip-go v0.3.5 // indirect github.com/syndtr/goleveldb v1.0.0 // indirect + github.com/tetratelabs/wazero v1.9.0 // indirect github.com/therootcompany/xz v1.0.1 // indirect github.com/tidwall/btree v1.4.3 // indirect github.com/tidwall/buntdb v1.3.0 // indirect @@ -101,6 +103,7 @@ require ( github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/ulikunitz/xz v0.5.12 // indirect + github.com/wasilibs/wazero-helpers v0.0.0-20240620070341-3dff1577cd52 // indirect github.com/yuin/goldmark v1.7.4 // indirect github.com/yuin/goldmark-emoji v1.0.3 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect @@ -113,12 +116,12 @@ require ( aead.dev/minisign v0.2.0 // indirect github.com/aymerick/douceur v0.2.0 // indirect github.com/cheggaaa/pb/v3 v3.1.4 - github.com/davecgh/go-spew v1.1.1 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/ebitengine/purego v0.4.0 github.com/golang/protobuf v1.5.3 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/gorilla/css v1.0.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/projectdiscovery/gologger v1.1.54 github.com/projectdiscovery/hmap v0.0.89 github.com/projectdiscovery/retryablehttp-go v1.0.114 diff --git a/go.sum b/go.sum index 67bebe1f..89537e27 100644 --- a/go.sum +++ b/go.sum @@ -87,12 +87,13 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0= github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= -github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo= -github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ= +github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 h1:2tV76y6Q9BB+NEBasnqvs7e49aEBFI8ejC89PSnWH+4= @@ -265,8 +266,9 @@ github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/projectdiscovery/blackrock v0.0.1 h1:lHQqhaaEFjgf5WkuItbpeCZv2DUIE45k0VbGJyft6LQ= @@ -331,6 +333,8 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= +github.com/tetratelabs/wazero v1.9.0 h1:IcZ56OuxrtaEz8UYNRHBrUa9bYeX9oVY93KspZZBf/I= +github.com/tetratelabs/wazero v1.9.0/go.mod h1:TSbcXCfFP0L2FGkRPxHphadXPjo1T6W+CseNNY7EkjM= github.com/therootcompany/xz v1.0.1 h1:CmOtsn1CbtmyYiusbfmhmkpAAETj0wBIH6kCYaX+xzw= github.com/therootcompany/xz v1.0.1/go.mod h1:3K3UH1yCKgBneZYhuQUvJ9HPD19UEXEI0BWbMn8qNMY= github.com/tidwall/assert v0.1.0 h1:aWcKyRBUAdLoVebxo95N7+YZVTFF/ASTr7BN4sLP6XI= @@ -364,6 +368,10 @@ github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9f github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc= github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/wasilibs/go-re2 v1.10.0 h1:vQZEBYZOCA9jdBMmrO4+CvqyCj0x4OomXTJ4a5/urQ0= +github.com/wasilibs/go-re2 v1.10.0/go.mod h1:k+5XqO2bCJS+QpGOnqugyfwC04nw0jaglmjrrkG8U6o= +github.com/wasilibs/wazero-helpers v0.0.0-20240620070341-3dff1577cd52 h1:OvLBa8SqJnZ6P+mjlzc2K7PM22rRUPE1x32G9DTPrC4= +github.com/wasilibs/wazero-helpers v0.0.0-20240620070341-3dff1577cd52/go.mod h1:jMeV4Vpbi8osrE/pKUxRZkVaA0EX7NZN0A9/oRzgpgY= github.com/weppos/publicsuffix-go v0.13.0/go.mod h1:z3LCPQ38eedDQSwmsSRW4Y7t2L8Ln16JPQ02lHAdn5k= github.com/weppos/publicsuffix-go v0.30.1-0.20230422193905-8fecedd899db h1:/WcxBne+5CbtbgWd/sV2wbravmr4sT7y52ifQaCgoLs= github.com/weppos/publicsuffix-go v0.30.1-0.20230422193905-8fecedd899db/go.mod h1:aiQaH1XpzIfgrJq3S1iw7w+3EDbRP7mF5fmwUhWyRUs= diff --git a/healthcheck/connection.go b/healthcheck/connection.go index 64b4c116..4f90167a 100644 --- a/healthcheck/connection.go +++ b/healthcheck/connection.go @@ -18,7 +18,7 @@ func CheckConnection(host string, port int, protocol string, timeout time.Durati address := net.JoinHostPort(host, strconv.Itoa(port)) conn, err := net.DialTimeout(protocol, address, timeout) if conn != nil { - conn.Close() + _ = conn.Close() } return ConnectionInfo{ diff --git a/healthcheck/path_permission_test.go b/healthcheck/path_permission_test.go index 013b2948..a4ca1949 100644 --- a/healthcheck/path_permission_test.go +++ b/healthcheck/path_permission_test.go @@ -11,7 +11,9 @@ func TestCheckPathPermission(t *testing.T) { t.Run("file with read and write permissions", func(t *testing.T) { filename := "testfile_read_write.txt" _, err := os.Create(filename) - defer os.Remove(filename) + defer func() { + _ = os.Remove(filename) + }() assert.NoError(t, err) permission := CheckPathPermission(filename) @@ -34,7 +36,9 @@ func TestCheckPathPermission(t *testing.T) { err = file.Chmod(0444) // read-only permissions assert.NoError(t, err) - defer os.Remove(filename) + defer func() { + _ = os.Remove(filename) + }() permission := CheckPathPermission(filename) assert.NoError(t, permission.Error) diff --git a/http/httputil_test.go b/http/httputil_test.go index d439a0c0..75ec91fd 100644 --- a/http/httputil_test.go +++ b/http/httputil_test.go @@ -24,7 +24,7 @@ func TestDumpResponseHeadersAndRaw(t *testing.T) { expectedResponseBody := "Hello, client" ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Del("Date") - fmt.Fprintln(w, expectedResponseBody) + _, _ = fmt.Fprintln(w, expectedResponseBody) })) defer ts.Close() diff --git a/http/response.go b/http/response.go index e6fa084c..984c15d8 100644 --- a/http/response.go +++ b/http/response.go @@ -49,7 +49,9 @@ func DumpResponseIntoBuffer(resp *http.Response, body bool, buff *bytes.Buffer) // DrainResponseBody drains the response body and closes it. func DrainResponseBody(resp *http.Response) { - defer resp.Body.Close() + defer func() { + _ = resp.Body.Close() + }() // don't reuse connection and just close if body length is more than 2 * MaxBodyRead // to avoid DOS _, _ = io.CopyN(io.Discard, resp.Body, 2*MaxBodyRead) diff --git a/ip/iputil.go b/ip/iputil.go index 3ffb0a98..4d873ffc 100644 --- a/ip/iputil.go +++ b/ip/iputil.go @@ -277,7 +277,9 @@ func WhatsMyIP() (string, error) { if err != nil { return "", err } - defer resp.Body.Close() + defer func() { + _ = resp.Body.Close() + }() if resp.StatusCode != http.StatusOK { return "", fmt.Errorf("error fetching ip: %s", resp.Status) @@ -304,7 +306,9 @@ func GetSourceIP(target string) (net.IP, error) { return nil, dialUpErr } - defer con.Close() + defer func() { + _ = con.Close() + }() if udpaddr, ok := con.LocalAddr().(*net.UDPAddr); ok { return udpaddr.IP, nil @@ -328,7 +332,7 @@ func GetBindableAddress(port int, ips ...string) (string, error) { errs = multierr.Append(errs, err) continue } - l.Close() + _ = l.Close() udpAddr := net.UDPAddr{ Port: port, IP: net.ParseIP(ip), @@ -339,7 +343,7 @@ func GetBindableAddress(port int, ips ...string) (string, error) { errs = multierr.Append(errs, err) continue } - lu.Close() + _ = lu.Close() // we found a bindable ip return ip, nil diff --git a/log/logutil_test.go b/log/logutil_test.go index 88fc654d..361b3c78 100644 --- a/log/logutil_test.go +++ b/log/logutil_test.go @@ -32,7 +32,7 @@ func TestEnableDefaultLogger(t *testing.T) { }() EnableDefaultLogger() log.Print(msg) - w.Close() + _ = w.Close() <-exit os.Stderr = &stderr require.Contains(t, buf.String(), msg) diff --git a/maps/mapsutil.go b/maps/mapsutil.go index 87adb8d6..1c77a8ae 100644 --- a/maps/mapsutil.go +++ b/maps/mapsutil.go @@ -154,7 +154,9 @@ func HTTPResponseToMap(resp *http.Response) (map[string]interface{}, error) { if err != nil { return nil, err } - resp.Body.Close() + defer func() { + _ = resp.Body.Close() + }() resp.Body = io.NopCloser(bytes.NewBuffer(body)) m["body"] = string(body) diff --git a/memoize/memoize.go b/memoize/memoize.go index 0fb653d6..2c7fa5ac 100644 --- a/memoize/memoize.go +++ b/memoize/memoize.go @@ -127,7 +127,7 @@ func Src(tpl, sourcePath string, source []byte, packageName string) ([]byte, err funcDeclaration.Name = nn.Name.Name funcDeclaration.SourcePackage = fileData.SourcePackage var funcSign strings.Builder - printer.Fprint(&funcSign, fset, nn.Type) + _ = printer.Fprint(&funcSign, fset, nn.Type) funcDeclaration.Signature = strings.Replace(funcSign.String(), "func", "func "+funcDeclaration.Name, 1) for _, comment := range nn.Doc.List { diff --git a/ml/naive_bayes/naive_bayes_classifier.go b/ml/naive_bayes/naive_bayes_classifier.go index db3b5cc4..7c920329 100644 --- a/ml/naive_bayes/naive_bayes_classifier.go +++ b/ml/naive_bayes/naive_bayes_classifier.go @@ -58,7 +58,9 @@ func NewClassifierFromFile(path string) (*NaiveBayesClassifier, error) { if err != nil { return classifier, err } - defer fl.Close() + defer func() { + _ = fl.Close() + }() return NewClassifierWithReader(fl) } @@ -85,7 +87,9 @@ func (c *NaiveBayesClassifier) SaveClassifierToFile(path string) error { if err != nil { return err } - defer fl.Close() + defer func() { + _ = fl.Close() + }() err = gob.NewEncoder(fl).Encode(&c) if err != nil { diff --git a/permission/permission_file_test.go b/permission/permission_file_test.go index 9a085dfe..13310afb 100644 --- a/permission/permission_file_test.go +++ b/permission/permission_file_test.go @@ -15,8 +15,12 @@ func TestFilePermissions(t *testing.T) { file, err := os.CreateTemp("", "testfile") require.Nil(t, err, "Failed to create test file: %v", err) testFileName := file.Name() - defer os.Remove(testFileName) - defer file.Close() + defer func() { + _ = os.Remove(testFileName) + }() + defer func() { + _ = file.Close() + }() // Set the file permissions err = file.Chmod(os.FileMode(AllReadWriteExecute)) @@ -35,8 +39,12 @@ func TestFilePermissions(t *testing.T) { require.Nil(t, err, "Failed to create test file: %v", err) testFileName := file.Name() - defer os.Remove(testFileName) - defer file.Close() + defer func() { + _ = os.Remove(testFileName) + }() + defer func() { + _ = file.Close() + }() // Set the file permissions err = file.Chmod(os.FileMode(UserReadWriteExecute)) @@ -56,8 +64,10 @@ func TestFilePermissions(t *testing.T) { require.Nil(t, err, "Failed to create test file: %v", err) testFileName := file.Name() - defer os.Remove(testFileName) - defer file.Close() + defer func() { + _ = file.Close() + _ = os.Remove(testFileName) + }() // Set the file permissions err = file.Chmod(os.FileMode(UserReadWriteExecute | GroupReadWriteExecute)) @@ -77,7 +87,9 @@ func TestUpdateFilePerm(t *testing.T) { // Create a temporary file for testing tempFile, err := os.CreateTemp("", "testfile") require.Nil(t, err, "Error creating temp file: %v", err) - defer os.Remove(tempFile.Name()) + defer func() { + _ = os.Remove(tempFile.Name()) + }() // Set the desired file permissions expectedPermissions := AllReadWrite diff --git a/process/docker.go b/process/docker.go index 30e7b762..865ca272 100644 --- a/process/docker.go +++ b/process/docker.go @@ -23,7 +23,9 @@ func RunningInContainer() (bool, string) { if err != nil { return false, "" } - defer f.Close() + defer func() { + _ = f.Close() + }() buff := bufio.NewScanner(f) for buff.Scan() { if strings.Contains(buff.Text(), "/docker") { @@ -38,7 +40,9 @@ func RunningInContainer() (bool, string) { if err != nil { return false, "" } - defer f2.Close() + defer func() { + _ = f2.Close() + }() buff2 := bufio.NewScanner(f2) for buff2.Scan() { if strings.Contains(buff2.Text(), "/docker") { diff --git a/proxy/burp.go b/proxy/burp.go index ebcd32f6..1c0085a1 100644 --- a/proxy/burp.go +++ b/proxy/burp.go @@ -22,7 +22,9 @@ func IsBurp(proxyURL string) (bool, error) { return false, err } - defer resp.Body.Close() + defer func() { + _ = resp.Body.Close() + }() return bytes.Contains(body, []byte("Burp Suite")), nil }) @@ -40,7 +42,10 @@ func ValidateOne(proxies ...string) (string, error) { if err != nil { return false, err } - defer resp.Body.Close() + + defer func() { + _ = resp.Body.Close() + }() return len(body) > 0, nil }) diff --git a/reader/conn_read.go b/reader/conn_read.go index dacc2205..526e7a3f 100644 --- a/reader/conn_read.go +++ b/reader/conn_read.go @@ -46,7 +46,9 @@ func ConnReadN(ctx context.Context, reader io.Reader, N int64) ([]byte, error) { // For an example of this scenario, refer to TestConnReadN#6. go func() { - defer pw.Close() + defer func() { + _ = pw.Close() + }() fn := func() (int64, error) { return io.CopyN(pw, io.LimitReader(reader, N), N) } diff --git a/reader/conn_read_test.go b/reader/conn_read_test.go index 64dd2910..c86755e0 100644 --- a/reader/conn_read_test.go +++ b/reader/conn_read_test.go @@ -57,7 +57,9 @@ func TestConnReadN(t *testing.T) { conn, err := tls.Dial("tcp", "projectdiscovery.io:443", &tls.Config{InsecureSkipVerify: true}) _ = conn.SetReadDeadline(time.Now().Add(5 * time.Second)) require.Nil(t, err, "could not connect to projectdiscovery.io over tls") - defer conn.Close() + defer func() { + _ = conn.Close() + }() _, err = conn.Write([]byte("GET / HTTP/1.1\r\nHost: projectdiscovery.io\r\nConnection: close\r\n\r\n")) require.Nil(t, err, "could not write to connection") data, err := ConnReadNWithTimeout(conn, -1, timeout) @@ -69,7 +71,9 @@ func TestConnReadN(t *testing.T) { conn, err := tls.Dial("tcp", "projectdiscovery.io:443", &tls.Config{InsecureSkipVerify: true}) _ = conn.SetReadDeadline(time.Now().Add(5 * time.Second)) require.Nil(t, err, "could not connect to projectdiscovery.io over tls") - defer conn.Close() + defer func() { + _ = conn.Close() + }() _, err = conn.Write([]byte("GET / HTTP/1.1\r\nHost: projectdiscovery.io\r\n\r\n")) require.Nil(t, err, "could not write to connection") data, err := ConnReadNWithTimeout(conn, -1, timeout) diff --git a/reader/examples/keypress/buffered/keypress.go b/reader/examples/keypress/buffered/keypress.go index 93a1685a..95d78b1e 100644 --- a/reader/examples/keypress/buffered/keypress.go +++ b/reader/examples/keypress/buffered/keypress.go @@ -15,8 +15,10 @@ func main() { Once: &sync.Once{}, } - stdr.Start() - defer stdr.Stop() + _ = stdr.Start() + defer func() { + _ = stdr.Stop() + }() for { data := make([]byte, stdr.BufferSize) diff --git a/reader/examples/keypress/raw/keypress.go b/reader/examples/keypress/raw/keypress.go index 2dcb81f8..c873dccf 100644 --- a/reader/examples/keypress/raw/keypress.go +++ b/reader/examples/keypress/raw/keypress.go @@ -16,8 +16,10 @@ func main() { Raw: true, } - stdr.Start() - defer stdr.Stop() + _ = stdr.Start() + defer func() { + _ = stdr.Stop() + }() for { data := make([]byte, 1) diff --git a/regexp/doc.go b/regexp/doc.go new file mode 100644 index 00000000..f231a239 --- /dev/null +++ b/regexp/doc.go @@ -0,0 +1,4 @@ +// Package regexp wraps the go regexp package with a few additional features: +// - Support for re2 syntax +// - Backtracking + compatibility with Perl5 and .NET syntax via github.com/dlclark/regexp2 +package regexp diff --git a/regexp/regexp.go b/regexp/regexp.go new file mode 100644 index 00000000..4f6811b9 --- /dev/null +++ b/regexp/regexp.go @@ -0,0 +1,311 @@ +package regexp + +import ( + "os" + "regexp" + + "github.com/dlclark/regexp2" + stringsutil "github.com/projectdiscovery/utils/strings" + "github.com/wasilibs/go-re2" +) + +// EngineType represents the type of regexp engine to use +type EngineType string + +const ( + // EngineStandard uses the standard Go regexp engine + EngineStandard EngineType = "standard" + // EngineRegexp2 uses the regexp2 engine for .NET-style regex + EngineRegexp2 EngineType = "regexp2" + // EngineRE2 uses the RE2 engine for linear time matching + EngineRE2 EngineType = "re2" + // EngineAuto automatically selects the most appropriate engine + EngineAuto EngineType = "auto" +) + +// Option represents a configuration option for the regexp +type Option func(*Regexp) + +// Regexp represents an extended regular expression with additional options +type Regexp struct { + standard *regexp.Regexp + regexp2 *regexp2.Regexp + re2 *re2.Regexp + engine EngineType + pattern string // Store the original pattern +} + +// WithEngine sets the regexp engine type +func WithEngine(engine EngineType) Option { + return func(r *Regexp) { + r.engine = engine + } +} + +// detectEngine analyzes the pattern and returns the most appropriate engine +func detectEngine(pattern string) EngineType { + // Check for .NET-style features that regexp2 handles better + hasNetStyle := stringsutil.ContainsAnyI(pattern, + "(?<", // Named capture groups + "(?=", // Positive lookahead + "(?!)", // Negative lookahead + "(?<=", // Positive lookbehind + "(?[0-9]+)", + input: "abc test123 def", + engine: EngineRegexp2, + want: []string{"test123", "123"}, + }, + { + name: "RE2 engine with capture group", + pattern: "test([0-9]+)", + input: "abc test123 def", + engine: EngineRE2, + want: []string{"test123", "123"}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + re, err := Compile(tt.pattern, WithEngine(tt.engine)) + if err != nil { + t.Fatalf("Compile() error = %v", err) + } + got := re.FindStringSubmatch(tt.input) + if len(got) != len(tt.want) { + t.Errorf("FindStringSubmatch() length = %v, want %v", len(got), len(tt.want)) + return + } + for i := range got { + if got[i] != tt.want[i] { + t.Errorf("FindStringSubmatch()[%d] = %v, want %v", i, got[i], tt.want[i]) + } + } + }) + } +} + +func TestFindStringSubmatchIndex(t *testing.T) { + tests := []struct { + name string + pattern string + input string + engine EngineType + want []int + }{ + { + name: "standard engine with capture group", + pattern: "test([0-9]+)", + input: "abc test123 def", + engine: EngineStandard, + want: []int{4, 11, 8, 11}, // [start, end, group1_start, group1_end] + }, + { + name: "standard engine no match", + pattern: "test([0-9]+)", + input: "abc testabc def", + engine: EngineStandard, + want: nil, + }, + { + name: "regexp2 engine with named capture", + pattern: "test(?[0-9]+)", + input: "abc test123 def", + engine: EngineRegexp2, + want: []int{4, 11, 8, 11}, // [start, end, group1_start, group1_end] + }, + { + name: "RE2 engine with capture group", + pattern: "test([0-9]+)", + input: "abc test123 def", + engine: EngineRE2, + want: []int{4, 11, 8, 11}, // [start, end, group1_start, group1_end] + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + re, err := Compile(tt.pattern, WithEngine(tt.engine)) + if err != nil { + t.Fatalf("Compile() error = %v", err) + } + got := re.FindStringSubmatchIndex(tt.input) + if len(got) != len(tt.want) { + t.Errorf("FindStringSubmatchIndex() length = %v, want %v", len(got), len(tt.want)) + return + } + for i := range got { + if got[i] != tt.want[i] { + t.Errorf("FindStringSubmatchIndex()[%d] = %v, want %v", i, got[i], tt.want[i]) + } + } + }) + } +} + +func TestString(t *testing.T) { + tests := []struct { + name string + pattern string + engine EngineType + }{ + { + name: "standard engine", + pattern: "test[0-9]+", + engine: EngineStandard, + }, + { + name: "regexp2 engine", + pattern: "test(?=123)", + engine: EngineRegexp2, + }, + { + name: "RE2 engine", + pattern: "test.*", + engine: EngineRE2, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + re, err := Compile(tt.pattern, WithEngine(tt.engine)) + if err != nil { + t.Fatalf("Compile() error = %v", err) + } + if got := re.String(); got != tt.pattern { + t.Errorf("String() = %v, want %v", got, tt.pattern) + } + }) + } +} diff --git a/routing/router_darwin.go b/routing/router_darwin.go index 9487d036..e5dd143a 100644 --- a/routing/router_darwin.go +++ b/routing/router_darwin.go @@ -102,9 +102,11 @@ func New() (Router, error) { default: // use last route type and print a warning if lastType != "" { + //nolint return nil, fmt.Errorf("using '%s' for unknown route type: '%s'\n", lastType, outputLine) } else { // we can't determine the route type + //nolint return nil, fmt.Errorf("could not determine route type for: '%s'", outputLine) } } diff --git a/scripts/versionbump/versionbump.go b/scripts/versionbump/versionbump.go index cb3af757..ff2162ae 100644 --- a/scripts/versionbump/versionbump.go +++ b/scripts/versionbump/versionbump.go @@ -69,7 +69,9 @@ func bumpVersion(fileName, varName, part string) (string, string, error) { if err != nil { return oldVersion, newVersion, fmt.Errorf("could not open file: %w", err) } - defer f.Close() + defer func() { + _ = f.Close() + }() if err := format.Node(f, fset, node); err != nil { return oldVersion, newVersion, fmt.Errorf("could not write to file: %w", err) diff --git a/scripts/versionbump/versionbump_test.go b/scripts/versionbump/versionbump_test.go index baa929bc..5dbb345e 100644 --- a/scripts/versionbump/versionbump_test.go +++ b/scripts/versionbump/versionbump_test.go @@ -114,7 +114,9 @@ func TestBumpVersionCLI(t *testing.T) { t.Fatalf("Cannot create temporary file: %s", err) } - defer os.Remove(tempFile.Name()) + defer func() { + _ = os.Remove(tempFile.Name()) + }() _, err = tempFile.Write([]byte(tc.fileContent)) if err != nil { diff --git a/update/gh.go b/update/gh.go index 8b6dbdd8..4c386404 100644 --- a/update/gh.go +++ b/update/gh.go @@ -90,7 +90,9 @@ func (d *GHReleaseDownloader) DownloadTool() (*bytes.Buffer, error) { if err != nil { return nil, err } - defer resp.Body.Close() + defer func() { + _ = resp.Body.Close() + }() if !HideProgressBar { bar := pb.New64(resp.ContentLength).SetMaxWidth(100) @@ -130,7 +132,9 @@ func (d *GHReleaseDownloader) GetReleaseChecksums() (map[string]string, error) { if err != nil { return nil, errorutil.NewWithErr(err).Msgf("failed to download checksum file") } - defer resp.Body.Close() + defer func() { + _ = resp.Body.Close() + }() bin, err := io.ReadAll(resp.Body) if err != nil { return nil, errorutil.NewWithErr(err).Msgf("failed to read checksum file") @@ -202,7 +206,9 @@ func (d *GHReleaseDownloader) DownloadAssetWithName(assetname string, showProgre if err != nil { return nil, errorutil.NewWithErr(err).Msgf("failed to download asset %v", assetname) } - defer resp.Body.Close() + defer func() { + _ = resp.Body.Close() + }() if showProgressBar { bar := pb.New64(resp.ContentLength).SetMaxWidth(100) @@ -226,7 +232,9 @@ func (d *GHReleaseDownloader) DownloadSourceWithCallback(showProgressBar bool, c if err != nil { return errorutil.NewWithErr(err).Msgf("failed to source of %v", d.repoName) } - defer resp.Body.Close() + defer func() { + _ = resp.Body.Close() + }() if showProgressBar { bar := pb.New64(resp.ContentLength).SetMaxWidth(100) bar.Start() diff --git a/update/types.go b/update/types.go index be3eb479..bcbf5487 100644 --- a/update/types.go +++ b/update/types.go @@ -25,12 +25,14 @@ const ( // FileExtension of this asset format func (a AssetFormat) FileExtension() string { - if a == Zip { + switch a { + case Zip: return ".zip" - } else if a == Tar { + case Tar: return ".tar.gz" + default: + return "" } - return "" } func IdentifyAssetFormat(assetName string) AssetFormat { diff --git a/update/update.go b/update/update.go index 1b037094..752e1bbd 100644 --- a/update/update.go +++ b/update/update.go @@ -128,7 +128,9 @@ func GetToolVersionCallback(toolName, version string) func() (string, error) { return "", errorutil.NewWithErr(err).Msgf("http Get %v failed", updateURL).WithTag("updater") } if resp.Body != nil { - defer resp.Body.Close() + defer func() { + _ = resp.Body.Close() + }() } if resp.StatusCode != 200 { return "", errorutil.NewWithTag("updater", "version check failed expected status 200 but got %v for GET %v", resp.StatusCode, updateURL) diff --git a/url/parsers.go b/url/parsers.go index 05e1a686..582b076c 100644 --- a/url/parsers.go +++ b/url/parsers.go @@ -88,7 +88,7 @@ func ParseAbsoluteURL(inputURL string, unsafe bool) (*URL, error) { if u.IsRelative { return nil, errorutil.NewWithTag("urlutil", "expected absolute url but got relative url input=%v,path=%v", inputURL, u.Path) } - if u.URL.Host == "" { + if u.Host == "" { return nil, errorutil.NewWithTag("urlutil", "something went wrong got empty host for absolute url=%v", inputURL) } return u, nil diff --git a/url/url.go b/url/url.go index 5919673c..cbd2bdc9 100644 --- a/url/url.go +++ b/url/url.go @@ -146,7 +146,7 @@ func (u *URL) UpdatePort(newport string) { if newport == "" { return } - if u.URL.Port() != "" { + if u.Port() != "" { u.Host = strings.Replace(u.Host, u.Port(), newport, 1) return } @@ -155,7 +155,7 @@ func (u *URL) UpdatePort(newport string) { // TrimPort if any func (u *URL) TrimPort() { - u.URL.Host = u.Hostname() + u.Host = u.Hostname() } // parseRelativePath parses relative path from Original Path without relying on @@ -220,7 +220,6 @@ func (u *URL) fetchParams() { u.Update() } - // copy parsed data from src to dst this does not include fragment or params func copy(dst *url.URL, src *url.URL) { dst.Host = src.Host