diff options
Diffstat (limited to 'raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/version')
| -rw-r--r-- | raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/version/version.go | 268 | ||||
| -rw-r--r-- | raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/version/version_test.go | 362 |
2 files changed, 0 insertions, 630 deletions
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/version/version.go b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/version/version.go deleted file mode 100644 index db8636e..0000000 --- a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/version/version.go +++ /dev/null @@ -1,268 +0,0 @@ -package version - -import ( - "encoding/json" - "fmt" - "os" - "os/exec" - "path/filepath" - "strings" - - "github.com/AvengeMedia/DankMaterialShell/core/internal/log" -) - -type VersionInfo struct { - Current string - Latest string - IsGit bool - IsBranch bool - IsTag bool - HasUpdate bool -} - -// VersionFetcher is an interface for fetching version information -type VersionFetcher interface { - GetCurrentVersion(dmsPath string) (string, error) - GetLatestVersion(dmsPath string) (string, error) -} - -// DefaultVersionFetcher is the default implementation that uses git/curl -type DefaultVersionFetcher struct{} - -func (d *DefaultVersionFetcher) GetCurrentVersion(dmsPath string) (string, error) { - if _, err := os.Stat(filepath.Join(dmsPath, ".git")); err == nil { - originalDir, err := os.Getwd() - if err != nil { - return "", err - } - defer func() { - if err := os.Chdir(originalDir); err != nil { - log.Warnf("failed to change back to original directory: %v", err) - } - }() - - if err := os.Chdir(dmsPath); err != nil { - return "", fmt.Errorf("failed to change to DMS directory: %w", err) - } - - tagCmd := exec.Command("git", "describe", "--exact-match", "--tags", "HEAD") - if tagOutput, err := tagCmd.Output(); err == nil { - return strings.TrimSpace(string(tagOutput)), nil - } - - branchCmd := exec.Command("git", "rev-parse", "--abbrev-ref", "HEAD") - if branchOutput, err := branchCmd.Output(); err == nil { - branch := strings.TrimSpace(string(branchOutput)) - revCmd := exec.Command("git", "rev-parse", "--short", "HEAD") - if revOutput, err := revCmd.Output(); err == nil { - rev := strings.TrimSpace(string(revOutput)) - return fmt.Sprintf("%s@%s", branch, rev), nil - } - return branch, nil - } - } - - cmd := exec.Command("dms", "--version") - if output, err := cmd.Output(); err == nil { - return strings.TrimSpace(string(output)), nil - } - - return "unknown", nil -} - -func (d *DefaultVersionFetcher) GetLatestVersion(dmsPath string) (string, error) { - if _, err := os.Stat(filepath.Join(dmsPath, ".git")); err == nil { - originalDir, err := os.Getwd() - if err != nil { - return "", err - } - defer func() { - if err := os.Chdir(originalDir); err != nil { - log.Warnf("failed to change back to original directory: %v", err) - } - }() - - if err := os.Chdir(dmsPath); err != nil { - return "", fmt.Errorf("failed to change to DMS directory: %w", err) - } - - currentRefCmd := exec.Command("git", "symbolic-ref", "-q", "HEAD") - currentRefOutput, _ := currentRefCmd.Output() - onBranch := len(currentRefOutput) > 0 - - if !onBranch { - tagCmd := exec.Command("git", "describe", "--exact-match", "--tags", "HEAD") - if _, err := tagCmd.Output(); err == nil { - // Add timeout to git fetch to prevent hanging - fetchCmd := exec.Command("timeout", "5s", "git", "fetch", "origin", "--tags", "--quiet") - if err := fetchCmd.Run(); err != nil { - log.Debugf("git fetch tags failed (continuing with local tags): %v", err) - } - - latestTagCmd := exec.Command("git", "tag", "-l", "v*", "--sort=-version:refname") - latestTagOutput, err := latestTagCmd.Output() - if err != nil { - return "", fmt.Errorf("failed to get latest tag: %w", err) - } - - tags := strings.Split(strings.TrimSpace(string(latestTagOutput)), "\n") - if len(tags) == 0 || tags[0] == "" { - return "", fmt.Errorf("no version tags found") - } - return tags[0], nil - } - } else { - branchCmd := exec.Command("git", "rev-parse", "--abbrev-ref", "HEAD") - branchOutput, err := branchCmd.Output() - if err != nil { - return "", fmt.Errorf("failed to get current branch: %w", err) - } - currentBranch := strings.TrimSpace(string(branchOutput)) - - // Add timeout to git fetch to prevent hanging - fetchCmd := exec.Command("timeout", "5s", "git", "fetch", "origin", currentBranch, "--quiet") - if err := fetchCmd.Run(); err != nil { - log.Debugf("git fetch branch failed (continuing with local ref): %v", err) - } - - remoteRevCmd := exec.Command("git", "rev-parse", "--short", fmt.Sprintf("origin/%s", currentBranch)) - remoteRevOutput, err := remoteRevCmd.Output() - if err != nil { - return "", fmt.Errorf("failed to get remote revision: %w", err) - } - remoteRev := strings.TrimSpace(string(remoteRevOutput)) - return fmt.Sprintf("%s@%s", currentBranch, remoteRev), nil - } - } - - // Add timeout to prevent hanging when GitHub is down - cmd := exec.Command("curl", "-s", "--max-time", "5", "https://api.github.com/repos/AvengeMedia/DankMaterialShell/releases/latest") - output, err := cmd.Output() - if err != nil { - return "", fmt.Errorf("failed to fetch latest release: %w", err) - } - - var result struct { - TagName string `json:"tag_name"` - } - if err := json.Unmarshal(output, &result); err != nil { - for _, line := range strings.Split(string(output), "\n") { - if strings.Contains(line, "\"tag_name\"") { - parts := strings.Split(line, "\"") - if len(parts) >= 4 { - return parts[3], nil - } - } - } - return "", fmt.Errorf("failed to parse latest version: %w", err) - } - - return result.TagName, nil -} - -// defaultFetcher is used by the public functions -var defaultFetcher VersionFetcher = &DefaultVersionFetcher{} - -func GetCurrentDMSVersion() (string, error) { - homeDir, err := os.UserHomeDir() - if err != nil { - return "", fmt.Errorf("failed to get home directory: %w", err) - } - - dmsPath := filepath.Join(homeDir, ".config", "quickshell", "dms") - if _, err := os.Stat(dmsPath); os.IsNotExist(err) { - return "", fmt.Errorf("DMS not installed") - } - - return defaultFetcher.GetCurrentVersion(dmsPath) -} - -func GetLatestDMSVersion() (string, error) { - homeDir, err := os.UserHomeDir() - if err != nil { - return "", fmt.Errorf("failed to get home directory: %w", err) - } - - dmsPath := filepath.Join(homeDir, ".config", "quickshell", "dms") - return defaultFetcher.GetLatestVersion(dmsPath) -} - -func GetDMSVersionInfo() (*VersionInfo, error) { - return GetDMSVersionInfoWithFetcher(defaultFetcher) -} - -func GetDMSVersionInfoWithFetcher(fetcher VersionFetcher) (*VersionInfo, error) { - homeDir, err := os.UserHomeDir() - if err != nil { - return nil, fmt.Errorf("failed to get home directory: %w", err) - } - - dmsPath := filepath.Join(homeDir, ".config", "quickshell", "dms") - if _, err := os.Stat(dmsPath); os.IsNotExist(err) { - return nil, fmt.Errorf("DMS not installed") - } - - current, err := fetcher.GetCurrentVersion(dmsPath) - if err != nil { - return nil, err - } - - latest, err := fetcher.GetLatestVersion(dmsPath) - if err != nil { - return nil, fmt.Errorf("failed to get latest version: %w", err) - } - - info := &VersionInfo{ - Current: current, - Latest: latest, - IsGit: strings.Contains(current, "@"), - IsBranch: strings.Contains(current, "@"), - IsTag: !strings.Contains(current, "@") && strings.HasPrefix(current, "v"), - } - - if info.IsBranch { - parts := strings.Split(current, "@") - latestParts := strings.Split(latest, "@") - if len(parts) == 2 && len(latestParts) == 2 { - info.HasUpdate = parts[1] != latestParts[1] - } - } else if info.IsTag { - info.HasUpdate = current != latest - } else { - info.HasUpdate = false - } - - return info, nil -} - -func CompareVersions(v1, v2 string) int { - v1 = strings.TrimPrefix(v1, "v") - v2 = strings.TrimPrefix(v2, "v") - - parts1 := strings.Split(v1, ".") - parts2 := strings.Split(v2, ".") - - maxLen := len(parts1) - if len(parts2) > maxLen { - maxLen = len(parts2) - } - - for i := 0; i < maxLen; i++ { - var p1, p2 int - if i < len(parts1) { - fmt.Sscanf(parts1[i], "%d", &p1) //nolint:errcheck - } - if i < len(parts2) { - fmt.Sscanf(parts2[i], "%d", &p2) //nolint:errcheck - } - - if p1 < p2 { - return -1 - } - if p1 > p2 { - return 1 - } - } - - return 0 -} diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/version/version_test.go b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/version/version_test.go deleted file mode 100644 index 1e424c1..0000000 --- a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/version/version_test.go +++ /dev/null @@ -1,362 +0,0 @@ -package version - -import ( - "os" - "os/exec" - "path/filepath" - "testing" - - mocks_version "github.com/AvengeMedia/DankMaterialShell/core/internal/mocks/version" - "github.com/AvengeMedia/DankMaterialShell/core/internal/utils" -) - -func TestCompareVersions(t *testing.T) { - tests := []struct { - v1 string - v2 string - expected int - }{ - {"v0.1.0", "v0.1.0", 0}, - {"v0.1.0", "v0.1.1", -1}, - {"v0.1.1", "v0.1.0", 1}, - {"v0.1.10", "v0.1.2", 1}, - {"v0.2.0", "v0.1.9", 1}, - {"0.1.0", "0.1.0", 0}, - {"1.0.0", "v1.0.0", 0}, - {"v1.2.3", "v1.2.4", -1}, - {"v2.0.0", "v1.9.9", 1}, - } - - for _, tt := range tests { - result := CompareVersions(tt.v1, tt.v2) - if result != tt.expected { - t.Errorf("CompareVersions(%q, %q) = %d; want %d", tt.v1, tt.v2, result, tt.expected) - } - } -} - -func TestGetDMSVersionInfo_Structure(t *testing.T) { - // Create a temp directory with a fake DMS installation - tempDir := t.TempDir() - dmsPath := filepath.Join(tempDir, ".config", "quickshell", "dms") - os.MkdirAll(dmsPath, 0o755) - - // Create a .git directory to simulate git installation - os.MkdirAll(filepath.Join(dmsPath, ".git"), 0o755) - - originalHome := os.Getenv("HOME") - defer os.Setenv("HOME", originalHome) - os.Setenv("HOME", tempDir) - - // Create mock fetcher - mockFetcher := mocks_version.NewMockVersionFetcher(t) - mockFetcher.EXPECT().GetCurrentVersion(dmsPath).Return("v0.1.0", nil) - mockFetcher.EXPECT().GetLatestVersion(dmsPath).Return("v0.1.1", nil) - - info, err := GetDMSVersionInfoWithFetcher(mockFetcher) - if err != nil { - t.Fatalf("GetDMSVersionInfoWithFetcher() failed: %v", err) - } - - if info == nil { - t.Fatal("GetDMSVersionInfoWithFetcher() returned nil") - } - - if info.Current != "v0.1.0" { - t.Errorf("Current version = %s, expected v0.1.0", info.Current) - } - - if info.Latest != "v0.1.1" { - t.Errorf("Latest version = %s, expected v0.1.1", info.Latest) - } - - if !info.HasUpdate { - t.Error("HasUpdate should be true when current != latest") - } - - if !info.IsTag { - t.Error("IsTag should be true for v0.1.0") - } - - t.Logf("Current: %s, Latest: %s, HasUpdate: %v", info.Current, info.Latest, info.HasUpdate) -} - -func TestGetDMSVersionInfo_BranchVersion(t *testing.T) { - tempDir := t.TempDir() - dmsPath := filepath.Join(tempDir, ".config", "quickshell", "dms") - os.MkdirAll(dmsPath, 0o755) - os.MkdirAll(filepath.Join(dmsPath, ".git"), 0o755) - - originalHome := os.Getenv("HOME") - defer os.Setenv("HOME", originalHome) - os.Setenv("HOME", tempDir) - - mockFetcher := mocks_version.NewMockVersionFetcher(t) - mockFetcher.EXPECT().GetCurrentVersion(dmsPath).Return("master@abc1234", nil) - mockFetcher.EXPECT().GetLatestVersion(dmsPath).Return("master@def5678", nil) - - info, err := GetDMSVersionInfoWithFetcher(mockFetcher) - if err != nil { - t.Fatalf("GetDMSVersionInfoWithFetcher() failed: %v", err) - } - - if !info.IsBranch { - t.Error("IsBranch should be true for branch@commit format") - } - - if !info.IsGit { - t.Error("IsGit should be true for branch@commit format") - } - - if !info.HasUpdate { - t.Error("HasUpdate should be true when commits differ") - } -} - -func TestGetDMSVersionInfo_NoUpdate(t *testing.T) { - tempDir := t.TempDir() - dmsPath := filepath.Join(tempDir, ".config", "quickshell", "dms") - os.MkdirAll(dmsPath, 0o755) - os.MkdirAll(filepath.Join(dmsPath, ".git"), 0o755) - - originalHome := os.Getenv("HOME") - defer os.Setenv("HOME", originalHome) - os.Setenv("HOME", tempDir) - - mockFetcher := mocks_version.NewMockVersionFetcher(t) - mockFetcher.EXPECT().GetCurrentVersion(dmsPath).Return("v0.1.0", nil) - mockFetcher.EXPECT().GetLatestVersion(dmsPath).Return("v0.1.0", nil) - - info, err := GetDMSVersionInfoWithFetcher(mockFetcher) - if err != nil { - t.Fatalf("GetDMSVersionInfoWithFetcher() failed: %v", err) - } - - if info.HasUpdate { - t.Error("HasUpdate should be false when current == latest") - } -} - -func TestGetCurrentDMSVersion_NotInstalled(t *testing.T) { - originalHome := os.Getenv("HOME") - defer os.Setenv("HOME", originalHome) - - tempDir := t.TempDir() - os.Setenv("HOME", tempDir) - - _, err := GetCurrentDMSVersion() - if err == nil { - t.Error("Expected error when DMS not installed, got nil") - } -} - -func TestGetCurrentDMSVersion_GitTag(t *testing.T) { - if !utils.CommandExists("git") { - t.Skip("git not available") - } - - tempDir := t.TempDir() - dmsPath := filepath.Join(tempDir, ".config", "quickshell", "dms") - os.MkdirAll(dmsPath, 0o755) - - originalHome := os.Getenv("HOME") - defer os.Setenv("HOME", originalHome) - os.Setenv("HOME", tempDir) - - exec.Command("git", "init", dmsPath).Run() - exec.Command("git", "-C", dmsPath, "config", "user.email", "test@test.com").Run() - exec.Command("git", "-C", dmsPath, "config", "user.name", "Test User").Run() - - testFile := filepath.Join(dmsPath, "test.txt") - os.WriteFile(testFile, []byte("test"), 0o644) - exec.Command("git", "-C", dmsPath, "add", ".").Run() - exec.Command("git", "-C", dmsPath, "commit", "-m", "initial").Run() - exec.Command("git", "-C", dmsPath, "tag", "v0.1.0").Run() - - version, err := GetCurrentDMSVersion() - if err != nil { - t.Fatalf("GetCurrentDMSVersion() failed: %v", err) - } - - if version != "v0.1.0" { - t.Errorf("Expected version v0.1.0, got %s", version) - } -} - -func TestGetCurrentDMSVersion_GitBranch(t *testing.T) { - if !utils.CommandExists("git") { - t.Skip("git not available") - } - - tempDir := t.TempDir() - dmsPath := filepath.Join(tempDir, ".config", "quickshell", "dms") - os.MkdirAll(dmsPath, 0o755) - - originalHome := os.Getenv("HOME") - defer os.Setenv("HOME", originalHome) - os.Setenv("HOME", tempDir) - - exec.Command("git", "init", dmsPath).Run() - exec.Command("git", "-C", dmsPath, "config", "user.email", "test@test.com").Run() - exec.Command("git", "-C", dmsPath, "config", "user.name", "Test User").Run() - exec.Command("git", "-C", dmsPath, "checkout", "-b", "master").Run() - - testFile := filepath.Join(dmsPath, "test.txt") - os.WriteFile(testFile, []byte("test"), 0o644) - exec.Command("git", "-C", dmsPath, "add", ".").Run() - exec.Command("git", "-C", dmsPath, "commit", "-m", "initial").Run() - - version, err := GetCurrentDMSVersion() - if err != nil { - t.Fatalf("GetCurrentDMSVersion() failed: %v", err) - } - - if version == "" { - t.Error("Expected non-empty version") - } - - if len(version) < 7 { - t.Errorf("Expected version with branch@commit format, got %s", version) - } -} - -func TestVersionInfo_IsGit(t *testing.T) { - tests := []struct { - current string - isGit bool - isBranch bool - isTag bool - }{ - {"v0.1.0", false, false, true}, - {"master@abc1234", true, true, false}, - {"dev@def5678", true, true, false}, - {"v0.2.0", false, false, true}, - {"unknown", false, false, false}, - } - - for _, tt := range tests { - info := &VersionInfo{ - IsGit: tt.isGit, - IsBranch: tt.isBranch, - IsTag: tt.isTag, - } - - actualIsGit := len(tt.current) > 0 && tt.current[0] != 'v' && tt.current != "unknown" - actualIsBranch := len(tt.current) > 0 && tt.current[0] != 'v' - actualIsTag := len(tt.current) > 0 && tt.current[0] == 'v' - - if tt.current == "unknown" { - actualIsGit = false - actualIsBranch = false - actualIsTag = false - } - - if info.IsGit != tt.isGit { - t.Errorf("For %s: IsGit = %v; want %v", tt.current, info.IsGit, tt.isGit) - } - if info.IsBranch != tt.isBranch { - t.Errorf("For %s: IsBranch = %v; want %v", tt.current, info.IsBranch, tt.isBranch) - } - if info.IsTag != tt.isTag { - t.Errorf("For %s: IsTag = %v; want %v", tt.current, info.IsTag, tt.isTag) - } - - _ = actualIsGit - _ = actualIsBranch - _ = actualIsTag - } -} - -func TestVersionInfo_HasUpdate_Branch(t *testing.T) { - tests := []struct { - current string - latest string - hasUpdate bool - }{ - {"master@abc1234", "master@abc1234", false}, - {"master@abc1234", "master@def5678", true}, - {"dev@abc1234", "dev@abc1234", false}, - {"dev@old1234", "dev@new5678", true}, - } - - for _, tt := range tests { - info := &VersionInfo{ - HasUpdate: tt.hasUpdate, - } - - if info.HasUpdate != tt.hasUpdate { - t.Errorf("For current=%s, latest=%s: HasUpdate = %v; want %v", - tt.current, tt.latest, info.HasUpdate, tt.hasUpdate) - } - } -} - -func TestVersionInfo_HasUpdate_Tag(t *testing.T) { - tests := []struct { - current string - latest string - hasUpdate bool - }{ - {"v0.1.0", "v0.1.0", false}, - {"v0.1.0", "v0.1.1", true}, - {"v0.1.5", "v0.1.5", false}, - {"v0.1.9", "v0.2.0", true}, - } - - for _, tt := range tests { - info := &VersionInfo{ - HasUpdate: tt.hasUpdate, - } - - if info.HasUpdate != tt.hasUpdate { - t.Errorf("For current=%s, latest=%s: HasUpdate = %v; want %v", - tt.current, tt.latest, info.HasUpdate, tt.hasUpdate) - } - } -} - -func TestGetLatestDMSVersion_FallbackParsing(t *testing.T) { - jsonResponse := `{ - "tag_name": "v0.1.17", - "name": "Release v0.1.17" - }` - - lines := []string{ - ` "tag_name": "v0.1.17",`, - ` "name": "Release v0.1.17"`, - } - - for _, line := range lines { - if len(line) > 0 && line[0:15] == ` "tag_name": "` { - parts := []string{"", "", "", "v0.1.17"} - version := parts[3] - if version != "v0.1.17" { - t.Errorf("Failed to parse version from line: %s", line) - } - } - } - - _ = jsonResponse -} - -func TestCompareVersions_EdgeCases(t *testing.T) { - tests := []struct { - v1 string - v2 string - expected int - }{ - {"", "", 0}, - {"v1", "v1", 0}, - {"v1.0", "v1", 0}, - {"v1.0.0", "v1.0", 0}, - {"v1.0.1", "v1.0", 1}, - {"v1", "v1.0.1", -1}, - } - - for _, tt := range tests { - result := CompareVersions(tt.v1, tt.v2) - if result != tt.expected { - t.Errorf("CompareVersions(%q, %q) = %d; want %d", tt.v1, tt.v2, result, tt.expected) - } - } -} |