main ece7682

atomic_test.go RawHistoryFolder

1package snapshot
2
3import (
4	"bytes"
5	"errors"
6	"os"
7	"path/filepath"
8	"testing"
9)
10
11func TestWriteImmutablePublishesAndReusesIdenticalData(t *testing.T) {
12	repo := NewRepository(privateDir(t))
13	dir := filepath.Join(repo.dir, "immutable")
14	if err := repo.ensurePrivateDirectory(dir); err != nil {
15		t.Fatal(err)
16	}
17
18	path := filepath.Join(dir, "object")
19	data := []byte("immutable")
20	verify := func(existing []byte) error {
21		if !bytes.Equal(existing, data) {
22			return errors.New("unexpected immutable data")
23		}
24		return nil
25	}
26	if err := repo.writeImmutable(path, data, verify); err != nil {
27		t.Fatal(err)
28	}
29	if err := repo.writeImmutable(path, data, verify); err != nil {
30		t.Fatal(err)
31	}
32	got, err := os.ReadFile(path)
33	if err != nil {
34		t.Fatal(err)
35	}
36	if !bytes.Equal(got, data) {
37		t.Fatalf("immutable data = %q, want %q", got, data)
38	}
39}
40
41func TestWithAtomicTempRemovesPublishedTemporaryFile(t *testing.T) {
42	repo := NewRepository(privateDir(t))
43	dir := filepath.Join(repo.dir, "temporary")
44	if err := repo.ensurePrivateDirectory(dir); err != nil {
45		t.Fatal(err)
46	}
47
48	var temporary string
49	if err := repo.withAtomicTemp(dir, []byte("data"), func(path string) (bool, error) {
50		temporary = path
51		info, err := os.Stat(path)
52		if err != nil {
53			return true, err
54		}
55		if got := info.Mode().Perm(); got != 0o600 {
56			t.Fatalf("temporary file mode = %o, want 600", got)
57		}
58		return true, nil
59	}); err != nil {
60		t.Fatal(err)
61	}
62	if _, err := os.Stat(temporary); !errors.Is(err, os.ErrNotExist) {
63		t.Fatalf("temporary file remains after publication: %v", err)
64	}
65}
66
67func TestWriteMutableConsumesTemporaryFile(t *testing.T) {
68	repo := NewRepository(privateDir(t))
69	path := filepath.Join(repo.dir, "HEAD")
70
71	if err := repo.writeMutable(path, []byte("head")); err != nil {
72		t.Fatalf("writeMutable error = %v", err)
73	}
74	got, err := os.ReadFile(path)
75	if err != nil {
76		t.Fatal(err)
77	}
78	if !bytes.Equal(got, []byte("head")) {
79		t.Fatalf("HEAD = %q, want %q", got, "head")
80	}
81	matches, err := filepath.Glob(filepath.Join(repo.dir, ".tmp-*"))
82	if err != nil || len(matches) != 0 {
83		t.Fatalf("temporary files after mutable write = %v, glob error = %v", matches, err)
84	}
85}

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