Skip to content

Commit 343c7e2

Browse files
committed
fix: Make session creation faster
Didn't benchmark but it's noticeably faster.
1 parent 9999060 commit 343c7e2

File tree

3 files changed

+49
-23
lines changed

3 files changed

+49
-23
lines changed

main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import (
1818
)
1919

2020
var (
21-
version = "1.0.11"
21+
version = "1.0.12"
2222
programFlag string
2323
autoYesFlag bool
2424
daemonFlag bool

session/git/worktree_ops.go

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,29 +14,52 @@ import (
1414

1515
// Setup creates a new worktree for the session
1616
func (g *GitWorktree) Setup() error {
17-
// Check if branch exists first
18-
repo, err := git.PlainOpen(g.repoPath)
17+
// Ensure worktrees directory exists early (can be done in parallel with branch check)
18+
worktreesDir, err := getWorktreeDirectory()
1919
if err != nil {
20-
return fmt.Errorf("failed to open repository: %w", err)
20+
return fmt.Errorf("failed to get worktree directory: %w", err)
2121
}
2222

23-
branchRef := plumbing.NewBranchReferenceName(g.branchName)
24-
if _, err := repo.Reference(branchRef, false); err == nil {
25-
// Branch exists, use SetupFromExistingBranch
26-
return g.SetupFromExistingBranch()
23+
// Create directory and check branch existence in parallel
24+
errChan := make(chan error, 2)
25+
var branchExists bool
26+
27+
// Goroutine for directory creation
28+
go func() {
29+
errChan <- os.MkdirAll(worktreesDir, 0755)
30+
}()
31+
32+
// Goroutine for branch check
33+
go func() {
34+
repo, err := git.PlainOpen(g.repoPath)
35+
if err != nil {
36+
errChan <- fmt.Errorf("failed to open repository: %w", err)
37+
return
38+
}
39+
40+
branchRef := plumbing.NewBranchReferenceName(g.branchName)
41+
if _, err := repo.Reference(branchRef, false); err == nil {
42+
branchExists = true
43+
}
44+
errChan <- nil
45+
}()
46+
47+
// Wait for both operations
48+
for i := 0; i < 2; i++ {
49+
if err := <-errChan; err != nil {
50+
return err
51+
}
2752
}
2853

29-
// Branch doesn't exist, create new worktree from HEAD
30-
return g.SetupNewWorktree()
54+
if branchExists {
55+
return g.setupFromExistingBranch()
56+
}
57+
return g.setupNewWorktree()
3158
}
3259

33-
// SetupFromExistingBranch creates a worktree from an existing branch
34-
func (g *GitWorktree) SetupFromExistingBranch() error {
35-
// Ensure worktrees directory exists
36-
worktreesDir := filepath.Join(g.repoPath, "worktrees")
37-
if err := os.MkdirAll(worktreesDir, 0755); err != nil {
38-
return fmt.Errorf("failed to create worktrees directory: %w", err)
39-
}
60+
// setupFromExistingBranch creates a worktree from an existing branch
61+
func (g *GitWorktree) setupFromExistingBranch() error {
62+
// Directory already created in Setup(), skip duplicate creation
4063

4164
// Clean up any existing worktree first
4265
_, _ = g.runGitCommand(g.repoPath, "worktree", "remove", "-f", g.worktreePath) // Ignore error if worktree doesn't exist
@@ -49,8 +72,8 @@ func (g *GitWorktree) SetupFromExistingBranch() error {
4972
return nil
5073
}
5174

52-
// SetupNewWorktree creates a new worktree from HEAD
53-
func (g *GitWorktree) SetupNewWorktree() error {
75+
// setupNewWorktree creates a new worktree from HEAD
76+
func (g *GitWorktree) setupNewWorktree() error {
5477
// Ensure worktrees directory exists
5578
worktreesDir := filepath.Join(g.repoPath, "worktrees")
5679
if err := os.MkdirAll(worktreesDir, 0755); err != nil {

session/tmux/tmux.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,19 +109,22 @@ func (t *TmuxSession) Start(workDir string) error {
109109
return fmt.Errorf("error starting tmux session: %w", err)
110110
}
111111

112-
// We need to close the ptmx, but we shouldn't close it before the command above finishes.
113-
// So, we poll for completion before closing.
112+
// Poll for session existence with exponential backoff
114113
timeout := time.After(2 * time.Second)
114+
sleepDuration := 5 * time.Millisecond
115115
for !t.DoesSessionExist() {
116116
select {
117117
case <-timeout:
118-
// Cleanup on window size update failure
119118
if cleanupErr := t.Close(); cleanupErr != nil {
120119
err = fmt.Errorf("%v (cleanup error: %v)", err, cleanupErr)
121120
}
122121
return fmt.Errorf("timed out waiting for tmux session %s: %v", t.sanitizedName, err)
123122
default:
124-
time.Sleep(time.Millisecond * 10)
123+
time.Sleep(sleepDuration)
124+
// Exponential backoff up to 50ms max
125+
if sleepDuration < 50*time.Millisecond {
126+
sleepDuration *= 2
127+
}
125128
}
126129
}
127130
ptmx.Close()

0 commit comments

Comments
 (0)