detached ece7682

web_control_darwin.go RawHistoryFolder

1//go:build darwin
2
3package app
4
5import (
6	"crypto/sha256"
7	"errors"
8	"fmt"
9	"net"
10	"os"
11	"path/filepath"
12	"syscall"
13	"time"
14
15	"golang.org/x/sys/unix"
16
17	"github.com/bnema/vev/internal/platform"
18	"github.com/bnema/vev/pkg/safedir"
19)
20
21// Darwin has no abstract Unix sockets, so the control interface binds a
22// 0600 socket file in a private per-user directory. Peer credentials, not
23// the discoverability of this path, protect the local control interface.
24func webControlAddress() string {
25	path, _ := filepath.Abs(platform.StateDir())
26	sum := sha256.Sum256([]byte(path))
27	dir := filepath.Join(os.TempDir(), fmt.Sprintf("vev-web-%d", os.Getuid()))
28	return filepath.Join(dir, fmt.Sprintf("%x.sock", sum[:8]))
29}
30
31func sameWebUID(conn *net.UnixConn) bool {
32	raw, err := conn.SyscallConn()
33	if err != nil {
34		return false
35	}
36	var credential *unix.Xucred
37	var peerErr error
38	err = raw.Control(func(fd uintptr) {
39		credential, peerErr = unix.GetsockoptXucred(int(fd), unix.SOL_LOCAL, unix.LOCAL_PEERCRED)
40	})
41	return err == nil && peerErr == nil && credential != nil && credential.Uid == uint32(os.Geteuid())
42}
43
44func bindWebControl() (*net.UnixListener, error) {
45	path := webControlAddress()
46	if err := safedir.EnsurePrivate(filepath.Dir(path)); err != nil {
47		return nil, fmt.Errorf("securing web control directory: %w", err)
48	}
49	listener, err := net.ListenUnix("unix", &net.UnixAddr{Name: path, Net: "unix"})
50	if err != nil {
51		if !errors.Is(err, syscall.EADDRINUSE) {
52			return nil, err
53		}
54		// Distinguish a live gateway from a stale socket left by a crash.
55		probeConn, probeErr := net.DialTimeout("unix", path, time.Second)
56		if probeErr == nil {
57			_ = probeConn.Close()
58			return nil, errors.New("web gateway control is already bound")
59		}
60		if !errors.Is(probeErr, syscall.ECONNREFUSED) && !errors.Is(probeErr, syscall.ENOENT) {
61			return nil, fmt.Errorf("probing web control socket: %w", probeErr)
62		}
63		if rmErr := os.Remove(path); rmErr != nil && !os.IsNotExist(rmErr) {
64			return nil, rmErr
65		}
66		listener, err = net.ListenUnix("unix", &net.UnixAddr{Name: path, Net: "unix"})
67		if err != nil {
68			return nil, err
69		}
70	}
71	return listener, secureWebControlSocket(listener, path)
72}
73
74func secureWebControlSocket(listener *net.UnixListener, path string) error {
75	if err := os.Chmod(path, 0o600); err != nil {
76		_ = listener.Close()
77		return fmt.Errorf("securing web control socket: %w", err)
78	}
79	return nil
80}

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