Skip to content

Commit f8aabde

Browse files
authored
Merge pull request #1130 from wakatime/bugfix/exclude-include-bool-param
Accept boolean value for exclude and include params
2 parents 1415a29 + 6e99337 commit f8aabde

File tree

4 files changed

+185
-75
lines changed

4 files changed

+185
-75
lines changed

cmd/heartbeat/heartbeat_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,44 @@ func TestSendHeartbeats_WithFiltering_Exclude(t *testing.T) {
234234
assert.Equal(t, 0, numCalls)
235235
}
236236

237+
func TestSendHeartbeats_WithFiltering_Exclude_All(t *testing.T) {
238+
resetSingleton(t)
239+
240+
testServerURL, router, tearDown := setupTestServer()
241+
defer tearDown()
242+
243+
var numCalls int
244+
245+
router.HandleFunc("/users/current/heartbeats.bulk", func(w http.ResponseWriter, _ *http.Request) {
246+
w.WriteHeader(http.StatusInternalServerError)
247+
248+
numCalls++
249+
})
250+
251+
v := viper.New()
252+
v.SetDefault("sync-offline-activity", 1000)
253+
v.Set("api-url", testServerURL)
254+
v.Set("category", "debugging")
255+
v.Set("entity", `\tmp\main.go`)
256+
v.Set("exclude", `true`)
257+
v.Set("entity-type", "file")
258+
v.Set("key", "00000000-0000-4000-8000-000000000000")
259+
v.Set("plugin", "plugin")
260+
v.Set("time", 1585598059.1)
261+
v.Set("timeout", 5)
262+
v.Set("write", true)
263+
264+
offlineQueueFile, err := os.CreateTemp(t.TempDir(), "")
265+
require.NoError(t, err)
266+
267+
defer offlineQueueFile.Close()
268+
269+
err = cmdheartbeat.SendHeartbeats(context.Background(), v, offlineQueueFile.Name())
270+
require.NoError(t, err)
271+
272+
assert.Equal(t, 0, numCalls)
273+
}
274+
237275
func TestSendHeartbeats_ExtraHeartbeats(t *testing.T) {
238276
resetSingleton(t)
239277

cmd/params/params.go

Lines changed: 38 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -437,12 +437,17 @@ func LoadHeartbeatParams(ctx context.Context, v *viper.Viper) (Heartbeat, error)
437437
timeSecs = float64(time.Now().UnixNano()) / 1000000000
438438
}
439439

440+
filterParams, err := loadFilterParams(ctx, v)
441+
if err != nil {
442+
return Heartbeat{}, fmt.Errorf("failed to load filter params: %s", err)
443+
}
444+
440445
projectParams, err := loadProjectParams(ctx, v)
441446
if err != nil {
442447
return Heartbeat{}, fmt.Errorf("failed to parse project params: %s", err)
443448
}
444449

445-
sanitizeParams, err := loadSanitizeParams(v)
450+
sanitizeParams, err := loadSanitizeParams(ctx, v)
446451
if err != nil {
447452
return Heartbeat{}, fmt.Errorf("failed to load sanitize params: %s", err)
448453
}
@@ -469,34 +474,30 @@ func LoadHeartbeatParams(ctx context.Context, v *viper.Viper) (Heartbeat, error)
469474
LinesInFile: linesInFile,
470475
LocalFile: vipertools.GetString(v, "local-file"),
471476
Time: timeSecs,
472-
Filter: loadFilterParams(ctx, v),
477+
Filter: filterParams,
473478
Project: projectParams,
474479
Sanitize: sanitizeParams,
475480
}, nil
476481
}
477482

478-
func loadFilterParams(ctx context.Context, v *viper.Viper) FilterParams {
483+
func loadFilterParams(ctx context.Context, v *viper.Viper) (FilterParams, error) {
479484
exclude := v.GetStringSlice("exclude")
480485
exclude = append(exclude, v.GetStringSlice("settings.exclude")...)
481486
exclude = append(exclude, v.GetStringSlice("settings.ignore")...)
482487

483-
logger := log.Extract(ctx)
484-
485488
var excludePatterns []regex.Regex
486489

487490
for _, s := range exclude {
488-
// make all regex case insensitive
489-
if !strings.HasPrefix(s, "(?i)") {
490-
s = "(?i)" + s
491-
}
492-
493-
compiled, err := regex.Compile(s)
491+
patterns, err := parseBoolOrRegexList(ctx, s)
494492
if err != nil {
495-
logger.Warnf("failed to compile exclude regex pattern %q", s)
496-
continue
493+
return FilterParams{}, fmt.Errorf(
494+
"failed to parse regex exclude param %q: %s",
495+
s,
496+
err,
497+
)
497498
}
498499

499-
excludePatterns = append(excludePatterns, compiled)
500+
excludePatterns = append(excludePatterns, patterns...)
500501
}
501502

502503
include := v.GetStringSlice("include")
@@ -505,18 +506,16 @@ func loadFilterParams(ctx context.Context, v *viper.Viper) FilterParams {
505506
var includePatterns []regex.Regex
506507

507508
for _, s := range include {
508-
// make all regex case insensitive
509-
if !strings.HasPrefix(s, "(?i)") {
510-
s = "(?i)" + s
511-
}
512-
513-
compiled, err := regex.Compile(s)
509+
patterns, err := parseBoolOrRegexList(ctx, s)
514510
if err != nil {
515-
logger.Warnf("failed to compile include regex pattern %q", s)
516-
continue
511+
return FilterParams{}, fmt.Errorf(
512+
"failed to parse regex include param %q: %s",
513+
s,
514+
err,
515+
)
517516
}
518517

519-
includePatterns = append(includePatterns, compiled)
518+
includePatterns = append(includePatterns, patterns...)
520519
}
521520

522521
return FilterParams{
@@ -532,10 +531,10 @@ func loadFilterParams(ctx context.Context, v *viper.Viper) FilterParams {
532531
"include-only-with-project-file",
533532
"settings.include_only_with_project_file",
534533
),
535-
}
534+
}, nil
536535
}
537536

538-
func loadSanitizeParams(v *viper.Viper) (SanitizeParams, error) {
537+
func loadSanitizeParams(ctx context.Context, v *viper.Viper) (SanitizeParams, error) {
539538
// hide branch names
540539
hideBranchNamesStr := vipertools.FirstNonEmptyString(
541540
v,
@@ -545,7 +544,7 @@ func loadSanitizeParams(v *viper.Viper) (SanitizeParams, error) {
545544
"settings.hidebranchnames",
546545
)
547546

548-
hideBranchNamesPatterns, err := parseBoolOrRegexList(hideBranchNamesStr)
547+
hideBranchNamesPatterns, err := parseBoolOrRegexList(ctx, hideBranchNamesStr)
549548
if err != nil {
550549
return SanitizeParams{}, fmt.Errorf(
551550
"failed to parse regex hide branch names param %q: %s",
@@ -563,7 +562,7 @@ func loadSanitizeParams(v *viper.Viper) (SanitizeParams, error) {
563562
"settings.hideprojectnames",
564563
)
565564

566-
hideProjectNamesPatterns, err := parseBoolOrRegexList(hideProjectNamesStr)
565+
hideProjectNamesPatterns, err := parseBoolOrRegexList(ctx, hideProjectNamesStr)
567566
if err != nil {
568567
return SanitizeParams{}, fmt.Errorf(
569568
"failed to parse regex hide project names param %q: %s",
@@ -583,7 +582,7 @@ func loadSanitizeParams(v *viper.Viper) (SanitizeParams, error) {
583582
"settings.hidefilenames",
584583
)
585584

586-
hideFileNamesPatterns, err := parseBoolOrRegexList(hideFileNamesStr)
585+
hideFileNamesPatterns, err := parseBoolOrRegexList(ctx, hideFileNamesStr)
587586
if err != nil {
588587
return SanitizeParams{}, fmt.Errorf(
589588
"failed to parse regex hide file names param %q: %s",
@@ -602,7 +601,7 @@ func loadSanitizeParams(v *viper.Viper) (SanitizeParams, error) {
602601
}
603602

604603
func loadProjectParams(ctx context.Context, v *viper.Viper) (ProjectParams, error) {
605-
submodulesDisabled, err := parseBoolOrRegexList(vipertools.GetString(v, "git.submodules_disabled"))
604+
submodulesDisabled, err := parseBoolOrRegexList(ctx, vipertools.GetString(v, "git.submodules_disabled"))
606605
if err != nil {
607606
return ProjectParams{}, fmt.Errorf(
608607
"failed to parse regex submodules disabled param: %s",
@@ -1154,9 +1153,11 @@ func (p StatusBar) String() string {
11541153
)
11551154
}
11561155

1157-
func parseBoolOrRegexList(s string) ([]regex.Regex, error) {
1156+
func parseBoolOrRegexList(ctx context.Context, s string) ([]regex.Regex, error) {
11581157
var patterns []regex.Regex
11591158

1159+
logger := log.Extract(ctx)
1160+
11601161
s = strings.ReplaceAll(s, "\r", "\n")
11611162
s = strings.Trim(s, "\n\t ")
11621163

@@ -1174,9 +1175,15 @@ func parseBoolOrRegexList(s string) ([]regex.Regex, error) {
11741175
continue
11751176
}
11761177

1178+
// make all regex case insensitive
1179+
if !strings.HasPrefix(s, "(?i)") {
1180+
s = "(?i)" + s
1181+
}
1182+
11771183
compiled, err := regex.Compile(s)
11781184
if err != nil {
1179-
return nil, fmt.Errorf("failed to compile regex %q: %s", s, err)
1185+
logger.Warnf("failed to compile regex pattern %q, it will be ignored", s)
1186+
continue
11801187
}
11811188

11821189
patterns = append(patterns, compiled)

cmd/params/params_internal_test.go

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package params
22

33
import (
4+
"context"
45
"regexp"
56
"testing"
67
"time"
@@ -13,6 +14,8 @@ import (
1314
)
1415

1516
func TestParseBoolOrRegexList(t *testing.T) {
17+
ctx := context.Background()
18+
1619
tests := map[string]struct {
1720
Input string
1821
Expected []regex.Regex
@@ -32,29 +35,29 @@ func TestParseBoolOrRegexList(t *testing.T) {
3235
"valid regex": {
3336
Input: "\t.?\n\t\n \n\t\twakatime.? \t\n",
3437
Expected: []regex.Regex{
35-
regex.NewRegexpWrap(regexp.MustCompile(".?")),
36-
regex.NewRegexpWrap(regexp.MustCompile("wakatime.?")),
38+
regex.NewRegexpWrap(regexp.MustCompile("(?i).?")),
39+
regex.NewRegexpWrap(regexp.MustCompile("(?i)wakatime.?")),
3740
},
3841
},
3942
"valid regex with windows style": {
4043
Input: "\t.?\r\n\t\t\twakatime.? \t\r\n",
4144
Expected: []regex.Regex{
42-
regex.NewRegexpWrap(regexp.MustCompile(".?")),
43-
regex.NewRegexpWrap(regexp.MustCompile("wakatime.?")),
45+
regex.NewRegexpWrap(regexp.MustCompile("(?i).?")),
46+
regex.NewRegexpWrap(regexp.MustCompile("(?i)wakatime.?")),
4447
},
4548
},
4649
"valid regex with old mac style": {
4750
Input: "\t.?\r\t\t\twakatime.? \t\r",
4851
Expected: []regex.Regex{
49-
regex.NewRegexpWrap(regexp.MustCompile(".?")),
50-
regex.NewRegexpWrap(regexp.MustCompile("wakatime.?")),
52+
regex.NewRegexpWrap(regexp.MustCompile("(?i).?")),
53+
regex.NewRegexpWrap(regexp.MustCompile("(?i)wakatime.?")),
5154
},
5255
},
5356
}
5457

5558
for name, test := range tests {
5659
t.Run(name, func(t *testing.T) {
57-
regex, err := parseBoolOrRegexList(test.Input)
60+
regex, err := parseBoolOrRegexList(ctx, test.Input)
5861
require.NoError(t, err)
5962

6063
assert.Equal(t, test.Expected, regex)

0 commit comments

Comments
 (0)