1{ lib, config, pkgs, ... }:
2
3with lib;
4let
5 cfg = config.modules.git;
6 home = config.home.homeDirectory;
7
8 excludesFile = pkgs.writeTextFile {
9 name = ".gitignore";
10 text = ''
11 # macOS: General
12 .DS_Store
13 .AppleDouble
14 .LSOverride
15 ._*
16
17 # macOS: Files that might appear in the root of a volume
18 .DocumentRevisions-V100
19 .fseventsd
20 .Spotlight-V100
21 .TemporaryItems
22 .Trashes
23 .VolumeIcon.icns
24 .com.apple.timemachine.donotpresent
25
26 # Xcode
27 xcuserdata/
28
29 # Linux: hidden files
30 *~
31 .fuse_hidden*
32 .directory
33 .Trash-*
34 .nfs*
35 '';
36 };
37
38 userType = types.submodule {
39 options = {
40 name = mkOption {
41 type = types.str;
42 example = "Sample Name";
43 };
44 email = mkOption {
45 type = types.str;
46 example = "sample@name.com";
47 };
48 };
49 };
50in {
51 options.modules.git = {
52 enable = mkOption {
53 default = true;
54 description = "Git Configuration";
55 type = types.bool;
56 };
57
58 user = mkOption {
59 default = {
60 name = "Phil Pluckthun";
61 email = "phil@kitten.sh";
62 };
63 description = "Git user information";
64 type = userType;
65 };
66
67 signingKey = mkOption {
68 description = "Git Signing key";
69 type = types.nullOr types.str;
70 };
71 };
72
73 config = mkIf cfg.enable {
74 home.packages = with pkgs; [ git-crypt ];
75
76 programs.git = {
77 enable = true;
78
79 signing = mkIf (cfg.signingKey != null) {
80 signByDefault = true;
81 key = cfg.signingKey;
82 };
83
84 ignores = [
85 ".DS_Store"
86 "*.sw[nop]"
87 "*.undodir"
88 ".env"
89 "*.orig"
90 ];
91
92 lfs = {
93 enable = true;
94 };
95
96 settings = {
97 user = cfg.user;
98
99 alias = {
100 s = "status -s";
101 last = "log -1";
102 lol = "log --pretty=longline --decorate --date=relative";
103 lrel = "log --pretty=longline --pretty=longline --graph --decorate --date=relative --boundary remotes/origin/HEAD...HEAD";
104 lloc = "log --pretty=longline --graph --decorate --date=relative --boundary ^remotes/origin/HEAD HEAD";
105 recommit = "commit -a --amend --no-edit";
106 pushf = "push --force-with-lease";
107 glog = "log --pretty=longline --decorate --all --graph --date=relative";
108 base = "!f() { git cherry remotes/origin/HEAD HEAD | awk '/^\\+/ {print $2;exit}'; }; f";
109 journal = "!f() { git commit -a -m \"$(date +'%Y-%m-%d %H:%M:%S')\"; }; f";
110 get = "!f() { git clone \"git@github.com:$1.git\" \"$HOME/git/$1\" --no-single-branch --shallow-since=\"1 year ago\"; }; f";
111 };
112
113 commit.gpgSign = true;
114 tag.gpgSign = true;
115 push.gpgSign = "if-asked";
116
117 column.ui = "auto";
118 color.ui = "auto";
119 init.defaultBranch = "main";
120 help.autocorrect = "prompt";
121
122 branch.sort = "-committerdate";
123 tag.sort = "-version:refname";
124 commit.verbose = true;
125
126 status = {
127 showUntrackedFiles = "all";
128 submoduleSummary = true;
129 };
130
131 diff = {
132 tool = "vimdiff";
133 submodule = "log";
134 algorithm = "histogram";
135 colorMoved = "plain";
136 colorMovedWS = "allow-indentation-change";
137 mnemonicPrefix = true;
138 compactionHeuristic = true;
139 rename = true;
140 };
141
142 push = {
143 default = "simple";
144 autoSetupRemote = true;
145 atomic = true;
146 };
147
148 rebase = {
149 autoSquash = true;
150 autoStash = true;
151 updateRefs = true;
152 missingCommitsCheck = "error";
153 };
154
155 merge = {
156 ff = "only";
157 tool = "vimdiff";
158 keepbackup = false;
159 };
160
161 fetch = {
162 prune = true;
163 pruneTags = true;
164 all = true;
165 };
166
167 rerere = {
168 enabled = true;
169 autoupdate = true;
170 };
171
172 core = {
173 autocrlf = false;
174 excludesfile = toString excludesFile;
175 };
176
177 pull.rebase = true;
178 difftool.prompt = false;
179 mergetool.prompt = true;
180 transfer.fsckobjects = true;
181 fetch.fsckobjects = true;
182 submodule.recurse = true;
183
184 receive = {
185 denyNonFastForwards = false;
186 shallowUpdate = true;
187 fsckObjects = true;
188 autogc = true;
189 };
190
191 "mergetool \"vimdiff\"".cmd = "nvim -d $LOCAL $REMOTE $MERGED -c '$wincmd w' -c 'wincmd J'";
192 pretty.longline = "tformat:%C(yellow)%h %Cred%D %Creset%<(50,mtrunc)%s %Cblue(%cd, %al)";
193
194 "remote \"origin\"" = {
195 fetch = "+refs/pull/*/head:refs/remotes/origin/pr/*";
196 partialclonefilter = "blob:none";
197 tagOpt = "--no-tags";
198 promisor = true;
199 pruneTags = true;
200 };
201 };
202 };
203 };
204}