feat(client): lodge remote binds a repository to another server

This commit is contained in:
hh committed 2026-10-02 22:05:10 +00:00
1 parent 45c81cfcaf
commit 91d83f3032
10 files changed
+639 -147

No files matched your search

+32 -14
View File
@@ -42,8 +42,12 @@ type diskFiles struct {
tracked map[string]bool
}
func worktreePath(dataDir string, repo *gitrepo.Repo) string {
return filepath.Join(dataDir, "repos", repo.Key, hashOf([]byte(repo.Root))[:16])
}
func (c *Client) statePath(repo *gitrepo.Repo) string {
return filepath.Join(c.DataDir, "repos", repo.Key, hashOf([]byte(repo.Root))[:16]+".json")
return worktreePath(c.DataDir, repo) + "-" + hashOf([]byte(c.URL))[:16] + ".json"
}
func (c *Client) loadState(repo *gitrepo.Repo) *worktreeState {
@@ -60,8 +64,7 @@ func (c *Client) loadState(repo *gitrepo.Repo) *worktreeState {
return st
}
func (c *Client) lock(repo *gitrepo.Repo) (func(), error) {
path := c.statePath(repo) + ".lock"
func flock(path string) (func(), error) {
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
return nil, err
}
@@ -76,31 +79,46 @@ func (c *Client) lock(repo *gitrepo.Repo) (func(), error) {
return func() { file.Close() }, nil
}
func (c *Client) Hook(ctx context.Context, dir string) error {
func (cfg *Config) Hook(ctx context.Context, dir string) error {
repo, err := gitrepo.Open(dir)
if err != nil {
return err
}
firstSight := !slices.Contains(c.Worktrees(), repo.Root)
_, err = c.Sync(ctx, repo.Root, firstSight)
firstSight := !slices.Contains(cfg.Worktrees(), repo.Root)
_, err = cfg.Sync(ctx, repo.Root, firstSight)
return err
}
func (c *Client) Sync(ctx context.Context, dir string, online bool) (Result, error) {
var res Result
func (cfg *Config) Sync(ctx context.Context, dir string, online bool) (Result, error) {
repo, err := gitrepo.Open(dir)
if err != nil {
return res, err
return Result{}, err
}
if err := c.register(repo.Root); err != nil {
return res, err
}
unlock, err := c.lock(repo)
worktree := worktreePath(cfg.DataDir, repo)
unlock, err := flock(worktree + ".lock")
if err != nil {
return res, err
return Result{}, err
}
defer unlock()
current, err := cfg.reload()
if err != nil {
return Result{}, err
}
c, err := current.Server(repo.Key)
if err != nil {
return Result{}, err
}
if err := cfg.register(repo.Root); err != nil {
return Result{}, err
}
if c.URL == current.URL {
_ = os.Rename(worktree+".json", c.statePath(repo))
}
return c.sync(ctx, repo, online)
}
func (c *Client) sync(ctx context.Context, repo *gitrepo.Repo, online bool) (Result, error) {
var res Result
st := c.loadState(repo)
for range maxPasses {
again, err := c.pass(ctx, repo, st, online, &res)