diff --git a/internal/storage/storage.go b/internal/storage/storage.go index 327a081..85ebd3e 100644 --- a/internal/storage/storage.go +++ b/internal/storage/storage.go @@ -346,18 +346,20 @@ func (d *DB) GetStats() (map[string]interface{}, error) { return stats, nil } -// ParseSemver parses a semantic version string and returns major, minor, patch components. -// It expects versions in the format "major.minor.patch" (e.g., "1.2.3"). -// Returns an error if the version string doesn't match the expected format. +// ParseSemver parses a version string and returns major, minor, patch components. +// It accepts "major.minor.patch" (e.g., "1.2.3") and "major.minor" (e.g., "2026.1"), +// treating the latter as patch 0. This handles JetBrains year-based versions like "2026.1". func ParseSemver(version string) (major, minor, patch int, err error) { - n, err := fmt.Sscanf(version, "%d.%d.%d", &major, &minor, &patch) - if err != nil { - return 0, 0, 0, fmt.Errorf("failed to parse version %q: %w", version, err) + n, scanErr := fmt.Sscanf(version, "%d.%d.%d", &major, &minor, &patch) + if n == 3 && scanErr == nil { + return major, minor, patch, nil } - if n != 3 { - return 0, 0, 0, fmt.Errorf("%w: %q", ErrInvalidVersionFmt, version) + // Fall back to two-component parse (e.g. "2026.1" → major=2026, minor=1, patch=0). + n2, scanErr2 := fmt.Sscanf(version, "%d.%d", &major, &minor) + if n2 == 2 && scanErr2 == nil { + return major, minor, 0, nil } - return major, minor, patch, nil + return 0, 0, 0, fmt.Errorf("failed to parse version %q: %w", version, scanErr) } // ExtractFilename extracts the filename from a file path using filepath.Base. diff --git a/internal/storage/storage_test.go b/internal/storage/storage_test.go index bd6108e..c20004e 100644 --- a/internal/storage/storage_test.go +++ b/internal/storage/storage_test.go @@ -1054,12 +1054,28 @@ func TestParseSemver(t *testing.T) { wantError: false, }, { - name: "invalid version - missing patch", + name: "two-component version - major.minor treated as patch 0", version: "1.2", - wantMajor: 0, - wantMinor: 0, + wantMajor: 1, + wantMinor: 2, wantPatch: 0, - wantError: true, + wantError: false, + }, + { + name: "intellij year-based version 2026.1", + version: "2026.1", + wantMajor: 2026, + wantMinor: 1, + wantPatch: 0, + wantError: false, + }, + { + name: "intellij year-based version 2025.3", + version: "2025.3", + wantMajor: 2025, + wantMinor: 3, + wantPatch: 0, + wantError: false, }, { name: "invalid version - extra part",