v0.2.0 80c61e3

flock_test.go RawHistoryFolder

1//go:build unix
2
3package lifecycle
4
5import (
6	"bufio"
7	"context"
8	"errors"
9	"fmt"
10	"io"
11	"os"
12	"os/exec"
13	"path/filepath"
14	"testing"
15	"time"
16
17	"github.com/stretchr/testify/require"
18)
19
20func TestLifecycleLockProcessHelper(t *testing.T) {
21	if os.Getenv("VEV_LIFECYCLE_LOCK_HELPER") != "1" {
22		t.Skip("helper process")
23	}
24
25	owner, err := TryAcquire(os.Getenv("VEV_LIFECYCLE_LOCK_DIR"))
26	require.NoError(t, err)
27	defer func() { require.NoError(t, owner.Release()) }()
28
29	_, err = fmt.Fprintln(os.Stdout, "locked")
30	require.NoError(t, err)
31	_, err = io.Copy(io.Discard, os.Stdin)
32	require.NoError(t, err)
33}
34
35func TestLifecycleLock(t *testing.T) {
36	t.Run("process contention and reacquire", testLifecycleLockProcessContentionAndReacquire)
37	t.Run("acquire cancellation", testLifecycleLockAcquireCancellation)
38	t.Run("unavailable runtime directory", testLifecycleLockUnavailableRuntimeDirectory)
39}
40
41func testLifecycleLockProcessContentionAndReacquire(t *testing.T) {
42	runtimeDir := filepath.Join(t.TempDir(), "runtime")
43	cmd := exec.Command(os.Args[0], "-test.run=^TestLifecycleLockProcessHelper$")
44	cmd.Env = append(os.Environ(),
45		"VEV_LIFECYCLE_LOCK_HELPER=1",
46		"VEV_LIFECYCLE_LOCK_DIR="+runtimeDir,
47	)
48	stdin, err := cmd.StdinPipe()
49	require.NoError(t, err)
50	stdout, err := cmd.StdoutPipe()
51	require.NoError(t, err)
52	cmd.Stderr = os.Stderr
53	require.NoError(t, cmd.Start())
54	defer func() {
55		_ = stdin.Close()
56		_ = cmd.Wait()
57	}()
58
59	line, err := bufio.NewReader(stdout).ReadString('\n')
60	require.NoError(t, err)
61	require.Equal(t, "locked\n", line)
62
63	_, err = TryAcquire(runtimeDir)
64	require.ErrorIs(t, err, ErrBusy)
65
66	require.NoError(t, stdin.Close())
67	require.NoError(t, cmd.Wait())
68
69	owner, err := TryAcquire(runtimeDir)
70	require.NoError(t, err)
71	require.NoError(t, owner.Release())
72	require.NoError(t, owner.Release(), "release is idempotent")
73}
74
75func testLifecycleLockAcquireCancellation(t *testing.T) {
76	runtimeDir := filepath.Join(t.TempDir(), "runtime")
77	owner, err := TryAcquire(runtimeDir)
78	require.NoError(t, err)
79	defer func() { require.NoError(t, owner.Release()) }()
80
81	ctx, cancel := context.WithCancel(context.Background())
82	cancel()
83
84	_, err = Acquire(ctx, runtimeDir, time.Millisecond)
85	require.ErrorIs(t, err, context.Canceled)
86}
87
88func testLifecycleLockUnavailableRuntimeDirectory(t *testing.T) {
89	runtimePath := t.TempDir() + "/not-a-directory"
90	require.NoError(t, os.WriteFile(runtimePath, []byte("occupied"), 0o600))
91
92	_, err := TryAcquire(runtimePath)
93	require.Error(t, err)
94	require.False(t, errors.Is(err, ErrBusy))
95}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 12

Tags 11

↑↓ moveenter openesc close