gitsync

package
v2.12.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 6, 2026 License: GPL-3.0 Imports: 26 Imported by: 0

Documentation

Index

Constants

View Source
const (
	AuthTypeToken = "token"
	AuthTypeSSH   = "ssh"
)

AuthType constants for authentication types.

Variables

View Source
var (
	// ErrNotEnabled is returned when Git sync is not enabled.
	ErrNotEnabled = errors.New("git sync is not enabled")

	// ErrNotConfigured is returned when Git sync is not properly configured.
	ErrNotConfigured = errors.New("git sync is not properly configured")

	// ErrRepoNotCloned is returned when the repository has not been cloned yet.
	ErrRepoNotCloned = errors.New("repository not cloned")

	// ErrAuthFailed is returned when authentication fails.
	ErrAuthFailed = errors.New("authentication failed")

	// ErrConflict is returned when a conflict is detected.
	ErrConflict = errors.New("conflict detected")

	// ErrOperationInProgress is returned when another sync operation is in progress.
	ErrOperationInProgress = errors.New("another sync operation is in progress")

	// ErrDAGNotFound is returned when the specified sync item is not found.
	ErrDAGNotFound = errors.New("sync item not found")

	// ErrInvalidDAGID is returned when the sync item ID format is invalid.
	ErrInvalidDAGID = errors.New("invalid sync item ID format")

	// ErrPushDisabled is returned when push operations are disabled.
	ErrPushDisabled = errors.New("push operations are disabled")

	// ErrNoChanges is returned when there are no changes to publish.
	ErrNoChanges = errors.New("no changes to publish")

	// ErrCannotForget is returned when a sync item cannot be forgotten.
	ErrCannotForget = errors.New("sync item cannot be forgotten")

	// ErrCannotDeleteUntracked is returned when deleting an untracked sync item.
	ErrCannotDeleteUntracked = errors.New("untracked sync items cannot be deleted from remote — use forget instead")

	// ErrNetworkError is returned when a network operation fails.
	ErrNetworkError = errors.New("network error")
)

Common errors for Git sync operations.

Functions

func ComputeContentHash

func ComputeContentHash(content []byte) string

ComputeContentHash computes the SHA256 hash of content bytes.

func IsConflict

func IsConflict(err error) bool

IsConflict checks if the error is a conflict error.

func IsDAGNotFound

func IsDAGNotFound(err error) bool

IsDAGNotFound checks if the error indicates a sync item was not found.

func IsInvalidDAGID

func IsInvalidDAGID(err error) bool

IsInvalidDAGID checks if the error indicates a sync item ID is invalid.

func IsNotEnabled

func IsNotEnabled(err error) bool

IsNotEnabled checks if the error indicates Git sync is not enabled.

Types

type AuthConfig

type AuthConfig struct {
	// Type is the authentication type: "token" or "ssh".
	Type string

	// Token is the personal access token for HTTPS authentication.
	Token string

	// SSHKeyPath is the path to the SSH private key file.
	SSHKeyPath string

	// SSHPassphrase is the passphrase for the SSH key (optional).
	SSHPassphrase string
}

AuthConfig holds authentication configuration for Git operations.

type AutoSyncConfig

type AutoSyncConfig struct {
	// Enabled indicates whether auto-sync is enabled.
	Enabled bool

	// OnStartup indicates whether to sync on server startup.
	OnStartup bool

	// Interval is the sync interval in seconds.
	// 0 means auto-sync is disabled (pull on startup only).
	Interval int
}

AutoSyncConfig holds configuration for automatic synchronization.

type CommitConfig

type CommitConfig struct {
	// AuthorName is the name to use for commits.
	// Defaults to "Dagu" if not specified.
	AuthorName string

	// AuthorEmail is the email to use for commits.
	// Defaults to "dagu@localhost" if not specified.
	AuthorEmail string
}

CommitConfig holds configuration for Git commits.

type CommitInfo

type CommitInfo struct {
	Hash      string
	Author    string
	Email     string
	Message   string
	Timestamp time.Time
}

CommitInfo represents information about a Git commit.

type Config

type Config struct {
	// Enabled indicates whether Git sync is enabled.
	Enabled bool

	// Repository is the Git repository URL.
	// Format: github.com/org/repo or https://github.com/org/repo.git
	Repository string

	// Branch is the branch to sync with.
	Branch string

	// Path is the subdirectory within the repository to sync.
	// Empty string means root directory.
	Path string

	// Auth contains authentication configuration.
	Auth AuthConfig

	// AutoSync contains auto-sync configuration.
	AutoSync AutoSyncConfig

	// PushEnabled indicates whether pushing changes is allowed.
	PushEnabled bool

	// Commit contains commit configuration.
	Commit CommitConfig
}

Config holds the configuration for Git sync functionality.

func NewConfigFromGlobal

func NewConfigFromGlobal(cfg config.GitSyncConfig) *Config

NewConfigFromGlobal creates a gitsync.Config from the global configuration.

func (*Config) GetAuthorEmail

func (c *Config) GetAuthorEmail() string

GetAuthorEmail returns the commit author email, using default if not set.

func (*Config) GetAuthorName

func (c *Config) GetAuthorName() string

GetAuthorName returns the commit author name, using default if not set.

func (*Config) IsValid

func (c *Config) IsValid() bool

IsValid returns true if the configuration is valid for sync operations.

type ConflictError

type ConflictError struct {
	DAGID         string
	RemoteCommit  string
	RemoteAuthor  string
	RemoteMessage string
}

ConflictError represents a conflict error with details.

func (*ConflictError) Error

func (e *ConflictError) Error() string

func (*ConflictError) Unwrap

func (e *ConflictError) Unwrap() error

type ConnectionResult

type ConnectionResult struct {
	Success bool   `json:"success"`
	Message string `json:"message,omitempty"`
	Error   string `json:"error,omitempty"`
}

ConnectionResult represents the result of a connection test.

type DAGNotFoundError

type DAGNotFoundError struct {
	DAGID string
}

DAGNotFoundError represents a sync item not found error with the ID.

func (*DAGNotFoundError) Error

func (e *DAGNotFoundError) Error() string

func (*DAGNotFoundError) Unwrap

func (e *DAGNotFoundError) Unwrap() error

type GitClient

type GitClient struct {
	// contains filtered or unexported fields
}

GitClient provides Git operations using go-git.

func NewGitClient

func NewGitClient(cfg *Config, repoPath string) *GitClient

NewGitClient creates a new Git client.

func (*GitClient) AddAndCommit

func (c *GitClient) AddAndCommit(filePath, message string) (string, error)

AddAndCommit stages a file and creates a commit. If the file content is already identical to HEAD (no changes), it returns the current HEAD hash instead of failing with an empty-commit error.

func (*GitClient) Clone

func (c *GitClient) Clone(ctx context.Context) error

Clone clones the repository.

func (*GitClient) CommitStaged

func (c *GitClient) CommitStaged(message string) (string, error)

CommitStaged creates a commit from the currently staged changes. If no changes are staged (clean tree), it returns the current HEAD hash.

func (*GitClient) Fetch

func (c *GitClient) Fetch(ctx context.Context) error

Fetch fetches updates from the remote.

func (*GitClient) FileExists

func (c *GitClient) FileExists(filePath string) bool

FileExists checks if a file exists in the working tree.

func (*GitClient) GetCommitInfo

func (c *GitClient) GetCommitInfo(commitHash string) (*CommitInfo, error)

GetCommitInfo returns information about a commit.

func (*GitClient) GetFileContentAtCommit

func (c *GitClient) GetFileContentAtCommit(filePath, commitHash string) ([]byte, error)

GetFileContentAtCommit returns the content of a file at a specific commit.

func (*GitClient) GetFilePath

func (c *GitClient) GetFilePath(relativePath string) string

GetFilePath returns the full path to a file in the repository.

func (*GitClient) GetHeadCommit

func (c *GitClient) GetHeadCommit() (string, error)

GetHeadCommit returns the current HEAD commit hash.

func (*GitClient) GetRemoteCommit

func (c *GitClient) GetRemoteCommit() (string, error)

GetRemoteCommit returns the latest commit hash from the remote branch.

func (*GitClient) IsCloned

func (c *GitClient) IsCloned() bool

IsCloned checks if the repository has been cloned.

func (*GitClient) ListFiles

func (c *GitClient) ListFiles(extensions []string) ([]string, error)

ListFiles returns all DAG files in the repository.

func (*GitClient) Open

func (c *GitClient) Open() error

Open opens an existing repository.

func (*GitClient) Pull

func (c *GitClient) Pull(ctx context.Context) (*PullResult, error)

Pull pulls updates and resets to the remote branch (hard reset for clean state).

func (*GitClient) Push

func (c *GitClient) Push(ctx context.Context) error

Push pushes commits to the remote.

func (*GitClient) RemoveFile

func (c *GitClient) RemoveFile(filePath string) error

RemoveFile stages a file removal (does not commit).

func (*GitClient) RemoveFiles

func (c *GitClient) RemoveFiles(filePaths []string) error

RemoveFiles stages multiple file removals (does not commit).

func (*GitClient) Reset

func (c *GitClient) Reset(filePath string) error

Reset resets a file to the version in HEAD.

func (*GitClient) SetupRemote

func (c *GitClient) SetupRemote() error

SetupRemote ensures the remote is configured correctly.

func (*GitClient) TestConnection

func (c *GitClient) TestConnection(_ context.Context) error

TestConnection tests the connection to the remote repository.

type InvalidDAGIDError

type InvalidDAGIDError struct {
	DAGID  string
	Reason string
}

InvalidDAGIDError represents an invalid sync item identifier.

func (*InvalidDAGIDError) Error

func (e *InvalidDAGIDError) Error() string

func (*InvalidDAGIDError) Unwrap

func (e *InvalidDAGIDError) Unwrap() error

type NetworkError

type NetworkError struct {
	Operation string
	Cause     error
}

NetworkError wraps network-related errors with context.

func (*NetworkError) Error

func (e *NetworkError) Error() string

func (*NetworkError) Unwrap

func (e *NetworkError) Unwrap() error

type OverallStatus

type OverallStatus struct {
	Enabled        bool                      `json:"enabled"`
	Repository     string                    `json:"repository,omitempty"`
	Branch         string                    `json:"branch,omitempty"`
	Summary        SummaryStatus             `json:"summary"`
	LastSyncAt     *time.Time                `json:"lastSyncAt,omitempty"`
	LastSyncCommit string                    `json:"lastSyncCommit,omitempty"`
	LastSyncStatus string                    `json:"lastSyncStatus,omitempty"`
	LastError      *string                   `json:"lastError,omitempty"`
	Items          map[string]*SyncItemState `json:"dags,omitempty"`
	Counts         StatusCounts              `json:"counts"`
}

OverallStatus represents the overall sync status.

type PullResult

type PullResult struct {
	PreviousCommit  string
	CurrentCommit   string
	AlreadyUpToDate bool
}

PullResult represents the result of a pull operation.

type Service

type Service interface {
	// Pull fetches and merges changes from the remote repository.
	Pull(ctx context.Context) (*SyncResult, error)

	// Publish commits and pushes a single sync item to the remote.
	Publish(ctx context.Context, itemID, message string, force bool) (*SyncResult, error)

	// PublishAll commits and pushes the specified sync items.
	PublishAll(ctx context.Context, message string, itemIDs []string) (*SyncResult, error)

	// Discard discards local changes for a sync item.
	Discard(ctx context.Context, itemID string) error

	// GetStatus returns the overall sync status.
	GetStatus(ctx context.Context) (*OverallStatus, error)

	// GetSyncItemStatus returns the sync status for a specific item.
	GetSyncItemStatus(ctx context.Context, itemID string) (*SyncItemState, error)

	// GetSyncItemDiff returns the diff between local and remote versions of an item.
	GetSyncItemDiff(ctx context.Context, itemID string) (*SyncItemDiff, error)

	// Forget removes state entries for missing, untracked, or conflicting items.
	Forget(ctx context.Context, itemIDs []string) ([]string, error)

	// Cleanup removes all missing entries from state.
	Cleanup(ctx context.Context) ([]string, error)

	// Delete removes an item from remote, local disk, and state.
	Delete(ctx context.Context, itemID, message string, force bool) error

	// DeleteBatch removes multiple items from remote, local disk, and state in a single commit.
	DeleteBatch(ctx context.Context, itemIDs []string, message string, force bool) ([]string, error)

	// DeleteAllMissing removes all missing items from remote, local, and state.
	DeleteAllMissing(ctx context.Context, message string) ([]string, error)

	// Move atomically renames an item across local filesystem, remote repository, and sync state.
	Move(ctx context.Context, oldID, newID, message string, force bool) error

	// GetConfig returns the current configuration.
	GetConfig(ctx context.Context) (*Config, error)

	// UpdateConfig updates the configuration.
	UpdateConfig(ctx context.Context, cfg *Config) error

	// TestConnection tests the connection to the remote repository.
	TestConnection(ctx context.Context) (*ConnectionResult, error)

	// Start starts the auto-sync background worker.
	Start(ctx context.Context) error

	// Stop stops the auto-sync background worker.
	Stop() error
}

Service defines the interface for Git sync operations.

func NewService

func NewService(cfg *Config, dagsDir, docsPath, dataDir string) Service

NewService creates a new Git sync service.

type State

type State struct {
	// Version is the state file format version.
	Version int `json:"version"`

	// Repository is the repository URL.
	Repository string `json:"repository"`

	// Branch is the branch being synced.
	Branch string `json:"branch"`

	// LastSyncAt is the timestamp of the last successful sync.
	LastSyncAt *time.Time `json:"lastSyncAt,omitempty"`

	// LastSyncCommit is the commit hash of the last sync.
	LastSyncCommit string `json:"lastSyncCommit,omitempty"`

	// LastSyncStatus is the status of the last sync operation.
	LastSyncStatus string `json:"lastSyncStatus,omitempty"`

	// LastError is the error message from the last failed sync.
	LastError *string `json:"lastError,omitempty"`

	// Items contains sync state keyed by normalized item ID.
	Items map[string]*SyncItemState `json:"dags"`
}

State represents the overall sync state.

type StateManager

type StateManager struct {
	// contains filtered or unexported fields
}

StateManager manages the sync state persistence.

func NewStateManager

func NewStateManager(dataDir string) *StateManager

NewStateManager creates a new state manager.

func (*StateManager) GetState

func (m *StateManager) GetState() (*State, error)

GetState returns the current state (from cache or loads from disk).

func (*StateManager) Load

func (m *StateManager) Load() (*State, error)

Load loads the state from disk.

func (*StateManager) Save

func (m *StateManager) Save(state *State) error

Save saves the state to disk.

type StatusCounts

type StatusCounts struct {
	Synced    int `json:"synced"`
	Modified  int `json:"modified"`
	Untracked int `json:"untracked"`
	Conflict  int `json:"conflict"`
	Missing   int `json:"missing"`
}

StatusCounts contains counts for each status type.

type SummaryStatus

type SummaryStatus string

SummaryStatus represents the summary status for the header badge.

const (
	SummarySynced   SummaryStatus = "synced"
	SummaryPending  SummaryStatus = "pending"
	SummaryConflict SummaryStatus = "conflict"
	SummaryMissing  SummaryStatus = "missing"
	SummaryError    SummaryStatus = "error"
)

type SyncError

type SyncError struct {
	ItemID  string `json:"dagId,omitempty"`
	Message string `json:"message"`
}

SyncError represents an error during sync.

type SyncItemDiff added in v2.12.0

type SyncItemDiff struct {
	ItemID        string     `json:"dagId"`
	FileExtension string     `json:"fileExtension"`
	Status        SyncStatus `json:"status"`
	LocalContent  string     `json:"localContent"`
	RemoteContent string     `json:"remoteContent,omitempty"`
	RemoteCommit  string     `json:"remoteCommit,omitempty"`
	RemoteAuthor  string     `json:"remoteAuthor,omitempty"`
	RemoteMessage string     `json:"remoteMessage,omitempty"`
}

SyncItemDiff represents the diff between local and remote versions of an item.

type SyncItemKind added in v2.12.0

type SyncItemKind string

SyncItemKind identifies a supported Git Sync item type.

const (
	SyncItemKindDAG SyncItemKind = "dag"
	SyncItemKindDoc SyncItemKind = "doc"
)

func SyncItemKindForID added in v2.12.0

func SyncItemKindForID(id string) SyncItemKind

SyncItemKindForID derives the item type from its normalized ID.

type SyncItemState added in v2.12.0

type SyncItemState struct {
	// Status is the current sync status.
	Status SyncStatus `json:"status"`

	// Kind identifies the tracked item type.
	Kind SyncItemKind `json:"kind,omitempty"`

	// FileExtension is the extension used by the tracked file.
	FileExtension string `json:"fileExtension,omitempty"`

	// BaseCommit is the commit hash when the item was last synced.
	BaseCommit string `json:"baseCommit,omitempty"`

	// LastSyncedHash is the content hash when the item was last synced.
	LastSyncedHash string `json:"lastSyncedHash,omitempty"`

	// LastSyncedAt is when the item was last synced.
	LastSyncedAt *time.Time `json:"lastSyncedAt,omitempty"`

	// ModifiedAt is when the item was last modified locally.
	ModifiedAt *time.Time `json:"modifiedAt,omitempty"`

	// LocalHash is the current local content hash.
	LocalHash string `json:"localHash,omitempty"`

	// RemoteCommit is the commit hash of the conflicting remote version.
	RemoteCommit string `json:"remoteCommit,omitempty"`

	// RemoteAuthor is the author of the conflicting remote commit.
	RemoteAuthor string `json:"remoteAuthor,omitempty"`

	// RemoteMessage is the commit message of the conflicting remote commit.
	RemoteMessage string `json:"remoteMessage,omitempty"`

	// ConflictDetectedAt is when the conflict was detected.
	ConflictDetectedAt *time.Time `json:"conflictDetectedAt,omitempty"`

	// PreviousStatus is the status before transitioning to missing.
	PreviousStatus string `json:"previousStatus,omitempty"`

	// MissingAt is when the file was first detected as missing.
	MissingAt *time.Time `json:"missingAt,omitempty"`

	// LastStatModTime is the file modification time used for stat-before-hash optimization.
	LastStatModTime *time.Time `json:"lastStatModTime,omitempty"`

	// LastStatSize is the file size used for stat-before-hash optimization.
	LastStatSize *int64 `json:"lastStatSize,omitempty"`
}

SyncItemState represents the sync state for a single item.

type SyncResult

type SyncResult struct {
	Success   bool        `json:"success"`
	Message   string      `json:"message,omitempty"`
	Synced    []string    `json:"synced,omitempty"`
	Modified  []string    `json:"modified,omitempty"`
	Conflicts []string    `json:"conflicts,omitempty"`
	Errors    []SyncError `json:"errors,omitempty"`
	Timestamp time.Time   `json:"timestamp"`
}

SyncResult represents the result of a sync operation.

type SyncStatus

type SyncStatus string

SyncStatus represents the synchronization status of a tracked item.

const (
	// StatusSynced indicates the item is in sync with remote.
	StatusSynced SyncStatus = "synced"

	// StatusModified indicates the item has local modifications.
	StatusModified SyncStatus = "modified"

	// StatusUntracked indicates the item exists only locally.
	StatusUntracked SyncStatus = "untracked"

	// StatusConflict indicates a conflict between local and remote versions.
	StatusConflict SyncStatus = "conflict"

	// StatusMissing indicates a previously tracked file is no longer on disk.
	StatusMissing SyncStatus = "missing"
)

type ValidationError

type ValidationError struct {
	Field   string
	Message string
}

ValidationError represents a validation error with field details.

func (*ValidationError) Error

func (e *ValidationError) Error() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL