this repo has no description
1{ pkgs, ... }: {
2 programs.jujutsu = {
3 enable = true;
4
5 settings = {
6 user.email = "~@hauleth.dev";
7 user.name = "Łukasz Niemier";
8
9 ui = {
10 default-command = ["log" "--template=log_compact"];
11
12 conflict-marker-style = "git";
13 };
14
15 aliases = {
16 tug = ["bookmark" "move" "--from" "closest_bookmark(@-)" "--to" "@-"];
17 pull = ["git" "fetch"];
18 push = ["git" "push"];
19 sync = [
20 "rebase"
21 "--source" "roots(trunk()..mutable())"
22 "--destination" "trunk()"
23 ];
24
25 # Put changes from `@` into another change
26 # Inverse of `extract`
27 inject = ["squash" "--from" "@" "--into"];
28
29 # Fetch changes from change into `@`
30 # Inverse of `inject`
31 extract = ["squash" "--into" "@" "--form"];
32
33 # 'jj sandwich xyz' to move xyz into the megamerge in parallel to everything
34 # else. See notes on 'megamerge()' above for how it's resolved.
35 sandwich = [ "rebase" "-B" "megamerge()" "-A" "trunk()" "-r"];
36 };
37
38 revset-aliases = {
39 "closest_bookmark(to)" = "heads(::to & bookmarks())";
40
41 # stack(x, n) is the set of mutable commits reachable from 'x', with 'n'
42 # parents. 'n' is often useful to customize the display and return set for
43 # certain operations. 'x' can be used to target the set of 'roots' to traverse,
44 # e.g. @ is the current stack.
45 "stack()" = "stack(@)";
46 "stack(x)" = "stack(x, 2)";
47 "stack(x, n)" = "ancestors(reachable(x, mutable()), n)";
48
49 # Find the megamerge. Mostly useful in combination with other aliases, primarily
50 # 'sandwich'. Normally when there's only one megamerge, sandwich works perfectly
51 # fine and is basically "magic". However, there are more complex cases; consider
52 # something like this which represents a forked repository of an upstream:
53 #
54 #
55 # ----> P1 ... Pn -----------\
56 # / \
57 # /---> X --\ (main) \
58 # B M1 --> T1 ... Tn --> M2 --> @
59 # \---> Y --/
60 #
61 # X and Y are typical features on top of base B, combined inside megamerge M1.
62 # However, we may want changes T1...Tn to go on top of M1, because (in my case)
63 # they're custom and will never go upstream, but are correctly published as part
64 # of the fork; Tn is where the main bookmark points. Finally, we have changes P1
65 # ... Pn which are private and should never be pushed upstream at all.
66 #
67 # In this case, sandwich will fail because 'reachable(stack(), merges())' will
68 # resolve to {M1, M2}, which is an invalid argument for 'rebase -B' due to not
69 # having an all: prefix modifier. So to handle that case, we allow the user
70 # to either specify the merge via literal tag "megamerge". In this case if we
71 # 'bookmark set megamerge -r M1' then sandwich will always work correctly.
72 "megamerge()" = "coalesce(present(megamerge), reachable(stack(), merges()))";
73 };
74
75 git = {
76 colocate = true;
77 write-change-id-header = true;
78 push-new-bookmarks = true;
79 };
80
81 colors = {
82 # change_id = "green";
83 "diff token".underline = false;
84 };
85
86 signing = {
87 behavior = "own";
88 backend = "ssh";
89 key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN7q0wm7C+EX0ORpRxeyhvWTT2BMPjSRQIZmbzPLIiHC";
90
91 backends.ssh = {
92 program = "/Applications/1Password.app/Contents/MacOS/op-ssh-sign";
93
94 allowed-signers = "~/.ssh/allowed_signers";
95 };
96 };
97
98 template-aliases = {
99 log_compact = ''
100 if(root,
101 format_root_commit(self),
102 label(if(current_working_copy, "working_copy"),
103 concat(
104 separate(" ",
105 format_short_change_id_with_hidden_and_divergent_info(self),
106 if(empty, label("empty", "(empty)")),
107 if(description,
108 description.first_line(),
109 label(if(empty, "empty"), description_placeholder),
110 ),
111 bookmarks,
112 tags,
113 working_copies,
114 if(git_head, label("git_head", "HEAD")),
115 if(conflict, label("conflict", "conflict")),
116 if(config("ui.show-cryptographic-signatures").as_boolean(),
117 format_short_cryptographic_signature(signature)),
118 if(!description && !empty, "\n" ++ diff.summary()),
119 ) ++ "\n",
120 ),
121 )
122 )
123 '';
124 };
125
126 templates = {
127 draft_commit_description =''
128 concat(
129 coalesce(description, default_commit_description, "\n"),
130 surround(
131 "\nJJ: This commit contains the following changes:\n", "",
132 indent("JJ: ", diff.stat(72)),
133 ),
134 "\nJJ: ignore-rest\n",
135 diff.git(),
136 )
137 '';
138 };
139 };
140 };
141
142 home.packages = [
143 pkgs.jjui
144 ];
145}