development_environment.go RawHistoryFolder

1package bootstrap
2
3import (
4	"fmt"
5	"os"
6	"path/filepath"
7)
8
9const (
10	developmentEnvironmentName             = "dev"
11	developmentPrivateMode     os.FileMode = 0o700
12)
13
14// ApplyDevelopmentEnvironment isolates the process from the user's XDG and
15// home directories when ENV=dev. It must run before GTK, CEF, or any adapter
16// can initialize and read process environment settings.
17func ApplyDevelopmentEnvironment() error {
18	if os.Getenv("ENV") != developmentEnvironmentName {
19		return nil
20	}
21
22	cwd, err := os.Getwd()
23	if err != nil {
24		return fmt.Errorf("resolve development environment root: %w", err)
25	}
26
27	devDir := filepath.Join(cwd, ".dev")
28	if err := ensureDevelopmentDirectory(devDir, true); err != nil {
29		return err
30	}
31
32	root := filepath.Join(devDir, "dumber")
33	paths := map[string]string{
34		"HOME":            filepath.Join(root, "home"),
35		"XDG_CONFIG_HOME": filepath.Join(root, "config"),
36		"XDG_DATA_HOME":   filepath.Join(root, "data"),
37		"XDG_STATE_HOME":  filepath.Join(root, "state"),
38		"XDG_CACHE_HOME":  filepath.Join(root, "cache"),
39	}
40	for _, path := range developmentPrivateDirectories(root, paths) {
41		if err := ensureDevelopmentDirectory(path, true); err != nil {
42			return err
43		}
44	}
45	for name, path := range paths {
46		if err := os.Setenv(name, path); err != nil {
47			return fmt.Errorf("set %s for development environment: %w", name, err)
48		}
49	}
50
51	return nil
52}
53
54// developmentPrivateDirectories returns every currently known path that Dumber
55// creates below the development sandbox. Creating and validating them before
56// GTK, CEF, logging, or the browser profile starts prevents those subsystems
57// from following a pre-existing sandbox symlink.
58func developmentPrivateDirectories(root string, paths map[string]string) []string {
59	enginesDir := filepath.Join(root, "engines")
60	cefDir := filepath.Join(enginesDir, "cef")
61	webkitDir := filepath.Join(enginesDir, "webkit")
62	runtimeDir := filepath.Join(root, "runtime")
63	return []string{
64		root,
65		paths["HOME"],
66		paths["XDG_CONFIG_HOME"],
67		paths["XDG_DATA_HOME"],
68		paths["XDG_STATE_HOME"],
69		paths["XDG_CACHE_HOME"],
70		filepath.Join(root, "logs"),
71		enginesDir,
72		cefDir,
73		filepath.Join(cefDir, "data"),
74		filepath.Join(cefDir, "runtime"),
75		filepath.Join(cefDir, "logs"),
76		webkitDir,
77		filepath.Join(webkitDir, "data"),
78		filepath.Join(webkitDir, "cache"),
79		filepath.Join(webkitDir, "runtime"),
80		filepath.Join(webkitDir, "logs"),
81		runtimeDir,
82		filepath.Join(runtimeDir, "cef"),
83		filepath.Join(runtimeDir, "webkit"),
84	}
85}
86
87func ensureDevelopmentDirectory(path string, private bool) error {
88	if err := os.MkdirAll(path, developmentPrivateMode); err != nil {
89		return fmt.Errorf("create development environment directory %q: %w", path, err)
90	}
91
92	info, err := os.Lstat(path)
93	if err != nil {
94		return fmt.Errorf("inspect development environment directory %q: %w", path, err)
95	}
96	if info.Mode()&os.ModeSymlink != 0 || !info.IsDir() {
97		return fmt.Errorf("development environment path %q must be a directory, not %s", path, info.Mode().Type())
98	}
99	if !private {
100		return nil
101	}
102	if err = os.Chmod(path, developmentPrivateMode); err != nil {
103		return fmt.Errorf("restrict development environment directory %q: %w", path, err)
104	}
105	info, err = os.Stat(path)
106	if err != nil {
107		return fmt.Errorf("verify development environment directory %q: %w", path, err)
108	}
109	if info.Mode().Perm() != developmentPrivateMode.Perm() {
110		return fmt.Errorf("development environment directory %q permissions are %04o, want 0700", path, info.Mode().Perm())
111	}
112	return nil
113}

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 8

Tags 42

↑↓ moveenter openesc close