move_pane_commit.go RawHistoryFolder

1package daemon
2
3import "github.com/bnema/vev/internal/domain/layout"
4
5// movePaneCommit owns pane-private validation and publication. The shared
6// moveTransaction already holds daemon, routing, ordered Session, and resize
7// fences. Every error below is returned before the first topology write.
8type movePaneCommit struct {
9	req                       movePaneRequest
10	source, destination       *session
11	sourceTab, destinationTab *tab
12	movedPane                 *pane
13	sourceGeneration          uint64
14	destinationGeneration     uint64
15}
16
17func (c *movePaneCommit) publishTopologyLocked(d *Daemon) (moveTopologyPublication, error) {
18	unlockTabs := lockMoveTabs(c.sourceTab, c.destinationTab)
19	c.movedPane.mu.Lock()
20	defer c.movedPane.mu.Unlock()
21	defer unlockTabs()
22
23	if !moveTabMemberLocked(c.source, c.sourceTab) || !moveTabMemberLocked(c.destination, c.destinationTab) || c.sourceTab == c.destinationTab ||
24		c.sourceTab.layoutGeneration != c.sourceGeneration || c.destinationTab.layoutGeneration != c.destinationGeneration ||
25		c.movedPane.stableID != string(c.req.SourcePaneID) || c.sourceTab.panes[c.movedPane.id] != c.movedPane ||
26		c.sourceTab.tree == nil || c.sourceTab.tree.Root == nil || !layout.ContainsLeaf(c.sourceTab.tree.Root, c.movedPane.id) ||
27		c.destinationTab.tree == nil || c.destinationTab.tree.Root == nil {
28		return moveTopologyPublication{}, errMoveStaleTarget
29	}
30	owner := c.movedPane.ownerSnapshot()
31	if owner != nil && (owner.session != c.source || owner.tab != c.sourceTab) {
32		return moveTopologyPublication{}, errMoveStaleTarget
33	}
34	candidate, err := prepareMovePaneCandidate(c.sourceTab, c.destinationTab, c.movedPane)
35	if err != nil {
36		return moveTopologyPublication{}, err
37	}
38	if candidate.sourceGeneration != c.sourceGeneration || candidate.destinationGeneration != c.destinationGeneration {
39		return moveTopologyPublication{}, errMoveStaleTarget
40	}
41	idx := -1
42	if candidate.removeSourceTab {
43		idx = indexMoveTabLocked(c.source, c.sourceTab)
44		if idx < 0 {
45			return moveTopologyPublication{}, errMoveStaleTarget
46		}
47	}
48
49	// Everything above is fallible. The remaining topology and owner writes form
50	// one in-memory publication and cannot turn into a Move rejection.
51	if candidate.removeSourceTab {
52		if len(c.source.tabs) > 1 {
53			c.source.prepareAttachmentViewsForRemovedTabLocked(c.sourceTab, idx)
54		}
55		c.source.tabs = append(c.source.tabs[:idx], c.source.tabs[idx+1:]...)
56	} else {
57		c.sourceTab.tree = candidate.sourceTree
58		c.sourceTab.bumpLayoutGenerationLocked()
59	}
60	delete(c.sourceTab.panes, candidate.sourceID)
61	if d.beforeMovePaneCommit != nil {
62		d.beforeMovePaneCommit()
63	}
64	c.destinationTab.tree = candidate.destinationTree
65	c.destinationTab.nextPaneID = candidate.destinationNextPaneID
66	c.destinationTab.panes[candidate.destinationID] = c.movedPane
67	c.destinationTab.bumpLayoutGenerationLocked()
68	c.movedPane.id = candidate.destinationID
69	oldOwner, newOwner := c.movedPane.publishOwnerLocked(c.destination, c.destinationTab, 0)
70	var syncCleanup syncTimerCleanup
71	syncCleanup.append(d.migratePaneSyncOwnerLocked(c.movedPane, oldOwner, newOwner))
72
73	return moveTopologyPublication{
74		sourceTab:        c.sourceTab,
75		destinationTab:   c.destinationTab,
76		movedPane:        c.movedPane,
77		syncCleanup:      syncCleanup,
78		sourceTabRemoved: candidate.removeSourceTab,
79		sourceEmpty:      len(c.source.tabs) == 0,
80	}, nil
81}

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