From 64095a2c8d5a3a72c55d7bd0737c5542a5aeee09 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Thu, 3 Jul 2025 22:38:37 +0300 Subject: feat: add SSH backup locations with --backup flag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add support for SSH backup locations (e.g., paul@server:git/) - Backup locations are one-way only (push only, never pull) - Automatic bare repository creation on SSH servers - Add --backup flag to opt-in to backup syncing - Backup locations are disabled by default for offline resilience - Update version to 0.2.0 This allows users to maintain private backups on home servers that may be offline without affecting regular sync operations. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- internal/config/config.go | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'internal/config') diff --git a/internal/config/config.go b/internal/config/config.go index ef8e3b6..7dedee7 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -10,10 +10,11 @@ import ( // Organization represents a git organization with its host and name type Organization struct { - Host string `json:"host"` - Name string `json:"name"` - GitHubToken string `json:"github_token,omitempty"` - CodebergToken string `json:"codeberg_token,omitempty"` + Host string `json:"host"` + Name string `json:"name"` + GitHubToken string `json:"github_token,omitempty"` + CodebergToken string `json:"codeberg_token,omitempty"` + BackupLocation bool `json:"backupLocation,omitempty"` // Mark this as a backup-only destination } // Config holds the application configuration @@ -83,8 +84,8 @@ func (c *Config) Validate() error { if org.Host == "" { return fmt.Errorf("organization %d: missing host", i) } - // Name can be empty for file:// URLs - if org.Name == "" && !strings.HasPrefix(org.Host, "file://") { + // Name can be empty for file:// URLs or SSH backup locations + if org.Name == "" && !strings.HasPrefix(org.Host, "file://") && !org.IsSSH() { return fmt.Errorf("organization %d: missing name", i) } } @@ -94,6 +95,10 @@ func (c *Config) Validate() error { // GetGitURL returns the git URL for an organization func (o *Organization) GetGitURL() string { + // For SSH backup locations with empty name, just return the host + if o.IsSSH() && o.Name == "" { + return o.Host + } return fmt.Sprintf("%s:%s", o.Host, o.Name) } @@ -137,3 +142,10 @@ func (c *Config) FindGitHubOrg() *Organization { return nil } +// IsSSH checks if the organization is a plain SSH location +func (o *Organization) IsSSH() bool { + // Check if it's not a known git hosting service and contains SSH-like syntax + return !o.IsGitHub() && !o.IsCodeberg() && !strings.HasPrefix(o.Host, "file://") && + (strings.Contains(o.Host, "@") || strings.Contains(o.Host, ":")) +} + -- cgit v1.2.3