syncbranch

package
v0.0.0-...-d497cf0 Latest Latest
Warning

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

Go to latest
Published: Mar 6, 2026 License: MIT Imports: 20 Imported by: 0

Documentation

Overview

Package syncbranch provides sync branch configuration and integrity checking.

Index

Constants

View Source
const (
	// ConfigKey is the database config key for sync branch
	ConfigKey = "sync.branch"

	// ConfigYAMLKey is the config.yaml key for sync branch
	ConfigYAMLKey = "sync-branch"

	// EnvVar is the environment variable for sync branch
	EnvVar = "BEADS_SYNC_BRANCH"
)
View Source
const (
	// RemoteSHAConfigKey stores the last known remote sync branch commit SHA.
	// This is used to detect force pushes on the remote sync branch.
	RemoteSHAConfigKey = "sync.remote_sha"
)

Config keys for sync branch integrity tracking

View Source
const SignificantDivergenceThreshold = 5

SignificantDivergenceThreshold is the number of commits at which divergence is considered significant When both local and remote are ahead by at least this many commits, the user should consider recovery options

Variables

This section is empty.

Functions

func ClearStoredRemoteSHA

func ClearStoredRemoteSHA(ctx context.Context, store storage.Storage) error

ClearStoredRemoteSHA removes the stored remote SHA. Use this when resetting the sync state (e.g., after accepting a rebase).

func Get

func Get(ctx context.Context, store storage.Storage) (string, error)

Get retrieves the sync branch configuration with the following precedence: 1. BEADS_SYNC_BRANCH environment variable 2. sync-branch from config.yaml (version controlled, shared across clones) 3. sync.branch from database config (legacy, for backward compatibility) 4. Empty string (meaning use current branch)

func GetCurrentBranch

func GetCurrentBranch(ctx context.Context) (string, error)

GetCurrentBranch returns the name of the current git branch

func GetFromYAML

func GetFromYAML() string

GetFromYAML retrieves sync branch from config.yaml only (no database lookup). This is useful for hooks and checks that need to know if sync-branch is configured in the version-controlled config without database access.

func GetRepoRoot

func GetRepoRoot(ctx context.Context) (string, error)

GetRepoRoot returns the git repository root directory For worktrees, this returns the main repository root (not the worktree root) The returned path is canonicalized to fix case on case-insensitive filesystems (GH#880)

func GetStoredRemoteSHA

func GetStoredRemoteSHA(ctx context.Context, store storage.Storage) (string, error)

GetStoredRemoteSHA returns the stored remote sync branch SHA.

func HasGitRemote

func HasGitRemote(ctx context.Context) bool

HasGitRemote checks if any git remote exists

func IsConfigured

func IsConfigured() bool

IsConfigured returns true if sync-branch is configured in config.yaml or env var. This is a fast check that doesn't require database access.

func IsConfiguredWithDB

func IsConfiguredWithDB(dbPath string) bool

IsConfiguredWithDB returns true if sync-branch is configured in any source: 1. BEADS_SYNC_BRANCH environment variable 2. sync-branch in config.yaml 3. sync.branch in database config

The dbPath parameter should be the path to the beads.db file. If dbPath is empty, it will use beads.FindDatabasePath() to locate the database. This function is safe to call even if the database doesn't exist (returns false in that case).

func IsSyncBranchSameAsCurrent

func IsSyncBranchSameAsCurrent(ctx context.Context, syncBranch string) bool

IsSyncBranchSameAsCurrent returns true if the sync branch is the same as the current branch. This is used to detect the case where we can't use a worktree because the branch is already checked out. In this case, we should commit directly to the current branch instead. See: https://github.com/untoldecay/BeadsLog/issues/519

func PushSyncBranch

func PushSyncBranch(ctx context.Context, repoRoot, syncBranch string) error

PushSyncBranch pushes the sync branch to remote. This is used after confirmation when sync.require_confirmation_on_mass_delete is enabled and a mass deletion was detected during merge.

Parameters:

  • ctx: Context for cancellation
  • repoRoot: Path to the git repository root
  • syncBranch: Name of the sync branch (e.g., "beads-sync")

Returns error if push fails.

func ResetToRemote

func ResetToRemote(ctx context.Context, repoRoot, syncBranch, jsonlPath string) error

ResetToRemote resets the local sync branch to match the remote state. This discards all local commits on the sync branch and adopts the remote's history. Use this when the sync branch has diverged significantly and you want to discard local changes.

Parameters:

  • ctx: Context for cancellation
  • repoRoot: Path to the git repository root
  • syncBranch: Name of the sync branch (e.g., "beads-sync")
  • jsonlPath: Path to the JSONL file in the main repo (will be updated with remote content)

Returns error if reset fails.

func Set

func Set(ctx context.Context, store storage.Storage, branch string) error

Set stores the sync branch configuration in both config.yaml AND the database. GH#909: Writing to both ensures bd doctor and migrate detection work correctly.

Config precedence on read (from Get function):

  1. BEADS_SYNC_BRANCH env var
  2. sync-branch in config.yaml (recommended, version controlled)
  3. sync.branch in database (legacy, for backward compatibility)

func Unset

func Unset(ctx context.Context, store storage.Storage) error

Unset removes the sync branch configuration from the database

func UpdateStoredRemoteSHA

func UpdateStoredRemoteSHA(ctx context.Context, store storage.Storage, repoRoot, syncBranch string) error

UpdateStoredRemoteSHA stores the current remote sync branch SHA in the database. Call this after a successful sync to track the remote state.

Parameters:

  • ctx: Context for cancellation
  • store: Storage interface for writing config
  • repoRoot: Path to the git repository root
  • syncBranch: Name of the sync branch (e.g., "beads-sync")

Returns error if the update fails.

func ValidateBranchName

func ValidateBranchName(name string) error

ValidateBranchName checks if a branch name is valid according to git rules

func ValidateSyncBranchName

func ValidateSyncBranchName(name string) error

ValidateSyncBranchName checks if a branch name is valid for use as sync.branch. GH#807: Setting sync.branch to 'main' or 'master' causes problems because the worktree mechanism will check out that branch, preventing the user from checking it out in their working directory.

Types

type CommitResult

type CommitResult struct {
	Committed bool   // True if changes were committed
	Pushed    bool   // True if changes were pushed
	Branch    string // The sync branch name
	Message   string // Commit message used
}

CommitResult contains information about a worktree commit operation

func CommitToSyncBranch

func CommitToSyncBranch(ctx context.Context, repoRoot, syncBranch, jsonlPath string, push bool) (*CommitResult, error)

CommitToSyncBranch commits JSONL changes to the sync branch using a git worktree. This allows committing to a different branch without changing the user's working directory.

IMPORTANT: Before committing, this function now performs a pre-emptive fetch and fast-forward if possible. This reduces the likelihood of divergence by ensuring we're building on top of the latest remote state when possible.

Parameters:

  • ctx: Context for cancellation
  • repoRoot: Path to the git repository root
  • syncBranch: Name of the sync branch (e.g., "beads-sync")
  • jsonlPath: Absolute path to the JSONL file in the main repo
  • push: If true, push to remote after commit

Returns CommitResult with details about what was done, or error if failed.

type DivergenceInfo

type DivergenceInfo struct {
	LocalAhead    int    // Number of commits local is ahead of remote
	RemoteAhead   int    // Number of commits remote is ahead of local
	Branch        string // The sync branch name
	Remote        string // The remote name (e.g., "origin")
	IsDiverged    bool   // True if both local and remote have commits the other doesn't
	IsSignificant bool   // True if divergence exceeds threshold (suggests recovery needed)
}

DivergenceInfo contains information about sync branch divergence from remote

func CheckDivergence

func CheckDivergence(ctx context.Context, repoRoot, syncBranch string) (*DivergenceInfo, error)

CheckDivergence checks the divergence between local sync branch and remote. This should be called before attempting sync operations to detect significant divergence that may require user intervention.

Parameters:

  • ctx: Context for cancellation
  • repoRoot: Path to the git repository root
  • syncBranch: Name of the sync branch (e.g., "beads-sync")

Returns DivergenceInfo with details about the divergence, or error if check fails.

type ForcePushStatus

type ForcePushStatus struct {
	// Detected is true if a force-push was detected on the remote sync branch.
	Detected bool

	// StoredSHA is the SHA we stored after the last successful sync.
	StoredSHA string

	// CurrentRemoteSHA is the current SHA of the remote sync branch.
	CurrentRemoteSHA string

	// Message provides a human-readable description of the status.
	Message string

	// Branch is the sync branch name.
	Branch string

	// Remote is the remote name (e.g., "origin").
	Remote string
}

ForcePushStatus represents the result of a force-push detection check.

func CheckForcePush

func CheckForcePush(ctx context.Context, store storage.Storage, repoRoot, syncBranch string) (*ForcePushStatus, error)

CheckForcePush detects if the remote sync branch has been force-pushed since the last sync.

A force-push is detected when: 1. We have a stored remote SHA from a previous sync 2. The stored SHA is NOT an ancestor of the current remote SHA

This means the remote history was rewritten (e.g., via force-push, rebase).

Parameters:

  • ctx: Context for cancellation
  • store: Storage interface for reading config
  • repoRoot: Path to the git repository root
  • syncBranch: Name of the sync branch (e.g., "beads-sync")

Returns ForcePushStatus with details about the check.

type PullResult

type PullResult struct {
	Pulled        bool   // True if pull was performed
	Branch        string // The sync branch name
	JSONLPath     string // Path to the synced JSONL in main repo
	Merged        bool   // True if divergent histories were merged
	FastForwarded bool   // True if fast-forward was possible
	Pushed        bool   // True if changes were pushed after merge

	// SafetyCheckTriggered indicates mass deletion was detected during merge
	// When true, callers should check config option sync.require_confirmation_on_mass_delete
	SafetyCheckTriggered bool
	// SafetyCheckDetails contains human-readable details about the mass deletion
	SafetyCheckDetails string
	// SafetyWarnings contains warning messages from the safety check
	// Caller should display these to the user as appropriate for their output format
	SafetyWarnings []string
}

PullResult contains information about a worktree pull operation

func PullFromSyncBranch

func PullFromSyncBranch(ctx context.Context, repoRoot, syncBranch, jsonlPath string, push bool, requireMassDeleteConfirmation ...bool) (*PullResult, error)

PullFromSyncBranch pulls changes from the sync branch and copies JSONL to the main repo. This fetches remote changes without affecting the user's working directory.

IMPORTANT: This function handles diverged histories gracefully by performing a content-based merge instead of relying on git's commit-level merge. When local and remote sync branches have diverged:

  1. Fetch remote changes (don't pull)
  2. Find the merge base
  3. Extract JSONL from base, local, and remote
  4. Perform 3-way content merge using bd's merge algorithm
  5. Reset to remote's history (adopt remote commit graph)
  6. Commit merged content on top

IMPORTANT: After successful content merge, auto-pushes to remote by default. Includes safety check: warns (but doesn't block) if >50% issues vanished AND >5 existed. "Vanished" means removed from issues.jsonl entirely, NOT status=closed.

IMPORTANT: If requireMassDeleteConfirmation is true and the safety check triggers, the function will NOT auto-push. Instead, it sets SafetyCheckTriggered=true in the result and the caller should prompt for confirmation then call PushSyncBranch.

This ensures sync never fails due to git merge conflicts, as we handle merging at the JSONL content level where we have semantic understanding of the data.

Parameters:

  • ctx: Context for cancellation
  • repoRoot: Path to the git repository root
  • syncBranch: Name of the sync branch (e.g., "beads-sync")
  • jsonlPath: Absolute path to the JSONL file in the main repo
  • push: If true, push to remote after merge
  • requireMassDeleteConfirmation: If true and mass deletion detected, skip push

Returns PullResult with details about what was done, or error if failed.

Jump to

Keyboard shortcuts

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