gitsync

package
v2.11.4 Latest Latest
Warning

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

Go to latest
Published: Aug 3, 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 DAG is not found.
	ErrDAGNotFound = errors.New("DAG not found")

	// ErrInvalidDAGID is returned when the DAG ID format is invalid.
	ErrInvalidDAGID = errors.New("invalid DAG 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 DAG cannot be forgotten.
	ErrCannotForget = errors.New("DAG cannot be forgotten")

	// ErrCannotDeleteUntracked is returned when trying to delete an untracked DAG.
	ErrCannotDeleteUntracked = errors.New("untracked DAGs 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 DAG was not found.

func IsInvalidDAGID

func IsInvalidDAGID(err error) bool

IsInvalidDAGID checks if the error indicates DAG 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 DAGDiff

type DAGDiff struct {
	DAGID         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"`
}

DAGDiff represents the diff between local and remote versions of a DAG.

type DAGNotFoundError

type DAGNotFoundError struct {
	DAGID string
}

DAGNotFoundError represents a DAG not found error with the ID.

func (*DAGNotFoundError) Error

func (e *DAGNotFoundError) Error() string

func (*DAGNotFoundError) Unwrap

func (e *DAGNotFoundError) Unwrap() error

type DAGState

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

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

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

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

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

	// ModifiedAt is when the DAG 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"`
}

DAGState represents the sync state for a single DAG.

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 DAG 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"`
	DAGs           map[string]*DAGState `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 DAG to the remote.
	Publish(ctx context.Context, dagID, message string, force bool) (*SyncResult, error)

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

	// Discard discards local changes for a DAG.
	Discard(ctx context.Context, dagID string) error

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

	// GetDAGStatus returns the sync status for a specific DAG.
	GetDAGStatus(ctx context.Context, dagID string) (*DAGState, error)

	// GetDAGDiff returns the diff between local and remote versions of a DAG.
	GetDAGDiff(ctx context.Context, dagID string) (*DAGDiff, error)

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

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

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

	// DeleteBatch removes multiple DAGs 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 DAGs from remote, local, and state.
	DeleteAllMissing(ctx context.Context, message string) ([]string, error)

	// Move atomically renames a DAG 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, 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"`

	// DAGs contains the sync state for each DAG.
	DAGs map[string]*DAGState `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 {
	DAGID   string `json:"dagId,omitempty"`
	Message string `json:"message"`
}

SyncError represents an error during sync.

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 DAG.

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

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

	// StatusUntracked indicates the DAG 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