this repo has no description
1{ pkgs, ... }:
2{
3 programs.jujutsu = {
4 enable = true;
5
6 settings = {
7 user.email = "~@hauleth.dev";
8 user.name = "Łukasz Niemier";
9
10 ui = {
11 default-command = [
12 "log"
13 "--template=log_compact"
14 ];
15
16 conflict-marker-style = "git";
17
18 pager = [
19 "sh"
20 "-c"
21 "${pkgs.diff-so-fancy}/bin/diff-so-fancy | less '--tabs=4' -RFX"
22 ];
23 diff-formatter = ":git";
24 };
25
26 merge-tools = {
27 difft.program = "${pkgs.difftastic}/bin/difft";
28 diffsitter.program = "${pkgs.diffsitter}/bin/diffsitter";
29 mergiraf.program = "${pkgs.mergiraf}/bin/mergiraf";
30 ai-desc.program = pkgs.writeShellScript "ai-diff" ''
31 diffout=`diff -Nur "$1" "$2"`
32
33 llm <<-PROMPT | fold -s -
34 Here is a diff from a git commit:
35
36 $diffout
37
38 Here is a summary (in no more than five sentences) of what this
39 commit implements:
40 PROMPT
41 '';
42 };
43
44 fix.tools = {
45 mix-format = {
46 command = [
47 "mix"
48 "format"
49 "--stdin-filename"
50 "$path"
51 "-"
52 ];
53 patterns = [
54 "glob:**/*.ex"
55 "glob:**/*.exs"
56 ];
57 };
58
59 nix-fmt = {
60 command = [
61 "nix"
62 "fmt"
63 "--"
64 "--stdin"
65 "$path"
66 ];
67 patterns = [ "glob:**/*.nix" ];
68 };
69 };
70
71 aliases = {
72 tug = [
73 "bookmark"
74 "advance"
75 ];
76 pull = [
77 "git"
78 "fetch"
79 ];
80 push = [
81 "git"
82 "push"
83 ];
84 sync = [
85 "rebase"
86 "--simplify-parents"
87 "--source"
88 "roots(trunk()..mutable())"
89 "--destination"
90 "trunk()"
91 ];
92
93 # Put changes from `@` into another change
94 # Inverse of `extract`
95 inject = [
96 "squash"
97 "--from"
98 "@"
99 "--into"
100 ];
101
102 # Fetch changes from change into `@`
103 # Inverse of `inject`
104 extract = [
105 "squash"
106 "--into"
107 "@"
108 "--form"
109 ];
110
111 # 'jj sandwich xyz' to move xyz into the megamerge in parallel to everything
112 # else. See notes on 'megamerge()' above for how it's resolved.
113 sandwich = [
114 "rebase"
115 "-B"
116 "megamerge()"
117 "-A"
118 "trunk()"
119 "-r"
120 ];
121 };
122
123 revset-aliases = {
124 "closest_bookmark(to)" = "heads(::to & bookmarks())";
125
126 # stack(x, n) is the set of mutable commits reachable from 'x', with 'n'
127 # parents. 'n' is often useful to customize the display and return set for
128 # certain operations. 'x' can be used to target the set of 'roots' to traverse,
129 # e.g. @ is the current stack.
130 "stack()" = "stack(@)";
131 "stack(x)" = "stack(x, 2)";
132 "stack(x, n)" = "ancestors(reachable(x, mutable()), n)";
133
134 # Find the megamerge. Mostly useful in combination with other aliases, primarily
135 # 'sandwich'. Normally when there's only one megamerge, sandwich works perfectly
136 # fine and is basically "magic". However, there are more complex cases; consider
137 # something like this which represents a forked repository of an upstream:
138 #
139 #
140 # ----> P1 ... Pn -----------\
141 # / \
142 # /---> X --\ (main) \
143 # B M1 --> T1 ... Tn --> M2 --> @
144 # \---> Y --/
145 #
146 # X and Y are typical features on top of base B, combined inside megamerge M1.
147 # However, we may want changes T1...Tn to go on top of M1, because (in my case)
148 # they're custom and will never go upstream, but are correctly published as part
149 # of the fork; Tn is where the main bookmark points. Finally, we have changes P1
150 # ... Pn which are private and should never be pushed upstream at all.
151 #
152 # In this case, sandwich will fail because 'reachable(stack(), merges())' will
153 # resolve to {M1, M2}, which is an invalid argument for 'rebase -B' due to not
154 # having an all: prefix modifier. So to handle that case, we allow the user
155 # to either specify the merge via literal tag "megamerge". In this case if we
156 # 'bookmark set megamerge -r M1' then sandwich will always work correctly.
157 "megamerge()" = "coalesce(present(megamerge), reachable(stack(), merges()))";
158 };
159
160 git = {
161 colocate = true;
162 write-change-id-header = true;
163 sign-on-push = true;
164 };
165
166 colors = {
167 # change_id = "green";
168 "diff token".underline = false;
169 };
170
171 signing = {
172 behavior = "drop";
173 backend = "ssh";
174 key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN7q0wm7C+EX0ORpRxeyhvWTT2BMPjSRQIZmbzPLIiHC";
175
176 backends.ssh = {
177 program = "/Applications/1Password.app/Contents/MacOS/op-ssh-sign";
178
179 allowed-signers = "~/.ssh/allowed_signers";
180 };
181 };
182
183 template-aliases = {
184 log_compact = ''
185 if(root,
186 format_root_commit(self),
187 label(if(current_working_copy, "working_copy"),
188 concat(
189 separate(" ",
190 format_short_change_id_with_change_offset(self),
191 if(empty, label("empty", "(empty)")),
192 if(description,
193 description.first_line(),
194 label(if(empty, "empty"), description_placeholder),
195 ),
196 bookmarks,
197 tags,
198 working_copies,
199 if(self.contained_in('first_parent(@)'), label("git_head", "HEAD")),
200 if(conflict, label("conflict", "conflict")),
201 if(config("ui.show-cryptographic-signatures").as_boolean(),
202 format_short_cryptographic_signature(signature)),
203 if(current_working_copy || (!description && !empty), "\n" ++ diff.summary()),
204 ) ++ "\n",
205 ),
206 )
207 )
208 '';
209 };
210
211 templates = {
212 draft_commit_description = ''
213 concat(
214 coalesce(description, default_commit_description, "\n"),
215 surround(
216 "\nJJ: This commit contains the following changes:\n", "",
217 indent("JJ: ", diff.stat(72)),
218 ),
219 "\nJJ: ignore-rest\n",
220 diff.git(),
221 )
222 '';
223 };
224 };
225 };
226
227 home.packages = [
228 pkgs.jjui
229 ];
230}