diff options
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | Cargo.lock | 229 | ||||
-rw-r--r-- | Cargo.toml | 10 | ||||
-rw-r--r-- | flake.lock | 87 | ||||
-rw-r--r-- | flake.nix | 101 | ||||
-rw-r--r-- | src/main.rs | 183 |
6 files changed, 613 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d3e728e --- /dev/null +++ b/.gitignore | |||
@@ -0,0 +1,3 @@ | |||
1 | .envrc | ||
2 | .direnv | ||
3 | /target | ||
diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..052dd11 --- /dev/null +++ b/Cargo.lock | |||
@@ -0,0 +1,229 @@ | |||
1 | # This file is automatically @generated by Cargo. | ||
2 | # It is not intended for manual editing. | ||
3 | version = 3 | ||
4 | |||
5 | [[package]] | ||
6 | name = "autocfg" | ||
7 | version = "1.0.1" | ||
8 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
9 | checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" | ||
10 | |||
11 | [[package]] | ||
12 | name = "bitflags" | ||
13 | version = "1.3.2" | ||
14 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
15 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" | ||
16 | |||
17 | [[package]] | ||
18 | name = "cc" | ||
19 | version = "1.0.72" | ||
20 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
21 | checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" | ||
22 | dependencies = [ | ||
23 | "jobserver", | ||
24 | ] | ||
25 | |||
26 | [[package]] | ||
27 | name = "cfg-if" | ||
28 | version = "1.0.0" | ||
29 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
30 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" | ||
31 | |||
32 | [[package]] | ||
33 | name = "form_urlencoded" | ||
34 | version = "1.0.1" | ||
35 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
36 | checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" | ||
37 | dependencies = [ | ||
38 | "matches", | ||
39 | "percent-encoding", | ||
40 | ] | ||
41 | |||
42 | [[package]] | ||
43 | name = "git2" | ||
44 | version = "0.13.25" | ||
45 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
46 | checksum = "f29229cc1b24c0e6062f6e742aa3e256492a5323365e5ed3413599f8a5eff7d6" | ||
47 | dependencies = [ | ||
48 | "bitflags", | ||
49 | "libc", | ||
50 | "libgit2-sys", | ||
51 | "log", | ||
52 | "openssl-probe", | ||
53 | "openssl-sys", | ||
54 | "url", | ||
55 | ] | ||
56 | |||
57 | [[package]] | ||
58 | name = "idna" | ||
59 | version = "0.2.3" | ||
60 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
61 | checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" | ||
62 | dependencies = [ | ||
63 | "matches", | ||
64 | "unicode-bidi", | ||
65 | "unicode-normalization", | ||
66 | ] | ||
67 | |||
68 | [[package]] | ||
69 | name = "jobserver" | ||
70 | version = "0.1.24" | ||
71 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
72 | checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" | ||
73 | dependencies = [ | ||
74 | "libc", | ||
75 | ] | ||
76 | |||
77 | [[package]] | ||
78 | name = "libc" | ||
79 | version = "0.2.116" | ||
80 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
81 | checksum = "565dbd88872dbe4cc8a46e527f26483c1d1f7afa6b884a3bd6cd893d4f98da74" | ||
82 | |||
83 | [[package]] | ||
84 | name = "libgit2-sys" | ||
85 | version = "0.12.26+1.3.0" | ||
86 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
87 | checksum = "19e1c899248e606fbfe68dcb31d8b0176ebab833b103824af31bddf4b7457494" | ||
88 | dependencies = [ | ||
89 | "cc", | ||
90 | "libc", | ||
91 | "libssh2-sys", | ||
92 | "libz-sys", | ||
93 | "openssl-sys", | ||
94 | "pkg-config", | ||
95 | ] | ||
96 | |||
97 | [[package]] | ||
98 | name = "libssh2-sys" | ||
99 | version = "0.2.23" | ||
100 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
101 | checksum = "b094a36eb4b8b8c8a7b4b8ae43b2944502be3e59cd87687595cf6b0a71b3f4ca" | ||
102 | dependencies = [ | ||
103 | "cc", | ||
104 | "libc", | ||
105 | "libz-sys", | ||
106 | "openssl-sys", | ||
107 | "pkg-config", | ||
108 | "vcpkg", | ||
109 | ] | ||
110 | |||
111 | [[package]] | ||
112 | name = "libz-sys" | ||
113 | version = "1.1.3" | ||
114 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
115 | checksum = "de5435b8549c16d423ed0c03dbaafe57cf6c3344744f1242520d59c9d8ecec66" | ||
116 | dependencies = [ | ||
117 | "cc", | ||
118 | "libc", | ||
119 | "pkg-config", | ||
120 | "vcpkg", | ||
121 | ] | ||
122 | |||
123 | [[package]] | ||
124 | name = "log" | ||
125 | version = "0.4.14" | ||
126 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
127 | checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" | ||
128 | dependencies = [ | ||
129 | "cfg-if", | ||
130 | ] | ||
131 | |||
132 | [[package]] | ||
133 | name = "matches" | ||
134 | version = "0.1.9" | ||
135 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
136 | checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" | ||
137 | |||
138 | [[package]] | ||
139 | name = "openssl-probe" | ||
140 | version = "0.1.5" | ||
141 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
142 | checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" | ||
143 | |||
144 | [[package]] | ||
145 | name = "openssl-sys" | ||
146 | version = "0.9.72" | ||
147 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
148 | checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb" | ||
149 | dependencies = [ | ||
150 | "autocfg", | ||
151 | "cc", | ||
152 | "libc", | ||
153 | "pkg-config", | ||
154 | "vcpkg", | ||
155 | ] | ||
156 | |||
157 | [[package]] | ||
158 | name = "percent-encoding" | ||
159 | version = "2.1.0" | ||
160 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
161 | checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" | ||
162 | |||
163 | [[package]] | ||
164 | name = "pkg-config" | ||
165 | version = "0.3.24" | ||
166 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
167 | checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" | ||
168 | |||
169 | [[package]] | ||
170 | name = "prompt" | ||
171 | version = "0.1.0" | ||
172 | dependencies = [ | ||
173 | "git2", | ||
174 | "tico", | ||
175 | ] | ||
176 | |||
177 | [[package]] | ||
178 | name = "tico" | ||
179 | version = "1.0.0" | ||
180 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
181 | checksum = "b9d73fbfe0205d9c15fb2768ac13d5bba2c39909bf326f5b36818aade6739464" | ||
182 | |||
183 | [[package]] | ||
184 | name = "tinyvec" | ||
185 | version = "1.5.1" | ||
186 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
187 | checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" | ||
188 | dependencies = [ | ||
189 | "tinyvec_macros", | ||
190 | ] | ||
191 | |||
192 | [[package]] | ||
193 | name = "tinyvec_macros" | ||
194 | version = "0.1.0" | ||
195 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
196 | checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" | ||
197 | |||
198 | [[package]] | ||
199 | name = "unicode-bidi" | ||
200 | version = "0.3.7" | ||
201 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
202 | checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" | ||
203 | |||
204 | [[package]] | ||
205 | name = "unicode-normalization" | ||
206 | version = "0.1.19" | ||
207 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
208 | checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" | ||
209 | dependencies = [ | ||
210 | "tinyvec", | ||
211 | ] | ||
212 | |||
213 | [[package]] | ||
214 | name = "url" | ||
215 | version = "2.2.2" | ||
216 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
217 | checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" | ||
218 | dependencies = [ | ||
219 | "form_urlencoded", | ||
220 | "idna", | ||
221 | "matches", | ||
222 | "percent-encoding", | ||
223 | ] | ||
224 | |||
225 | [[package]] | ||
226 | name = "vcpkg" | ||
227 | version = "0.2.15" | ||
228 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
229 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" | ||
diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..9c24663 --- /dev/null +++ b/Cargo.toml | |||
@@ -0,0 +1,10 @@ | |||
1 | [package] | ||
2 | name = "prompt" | ||
3 | version = "0.1.0" | ||
4 | edition = "2018" | ||
5 | |||
6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
7 | |||
8 | [dependencies] | ||
9 | tico = "1.0.0" | ||
10 | git2 = "0.13.25" | ||
diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..1e575e3 --- /dev/null +++ b/flake.lock | |||
@@ -0,0 +1,87 @@ | |||
1 | { | ||
2 | "nodes": { | ||
3 | "fenix": { | ||
4 | "inputs": { | ||
5 | "nixpkgs": [ | ||
6 | "nixpkgs" | ||
7 | ], | ||
8 | "rust-analyzer-src": "rust-analyzer-src" | ||
9 | }, | ||
10 | "locked": { | ||
11 | "lastModified": 1642141613, | ||
12 | "narHash": "sha256-WFS7T5oOLD8anu/77iz7EPz7zQsJZtP5qVa5485k3dI=", | ||
13 | "owner": "nix-community", | ||
14 | "repo": "fenix", | ||
15 | "rev": "d75ffc9f1d3b60bb597e48ae01f486a6de27d30e", | ||
16 | "type": "github" | ||
17 | }, | ||
18 | "original": { | ||
19 | "owner": "nix-community", | ||
20 | "repo": "fenix", | ||
21 | "type": "github" | ||
22 | } | ||
23 | }, | ||
24 | "gitignore": { | ||
25 | "inputs": { | ||
26 | "nixpkgs": [ | ||
27 | "nixpkgs" | ||
28 | ] | ||
29 | }, | ||
30 | "locked": { | ||
31 | "lastModified": 1635165013, | ||
32 | "narHash": "sha256-o/BdVjNwcB6jOmzZjOH703BesSkkS5O7ej3xhyO8hAY=", | ||
33 | "owner": "hercules-ci", | ||
34 | "repo": "gitignore.nix", | ||
35 | "rev": "5b9e0ff9d3b551234b4f3eb3983744fa354b17f1", | ||
36 | "type": "github" | ||
37 | }, | ||
38 | "original": { | ||
39 | "owner": "hercules-ci", | ||
40 | "repo": "gitignore.nix", | ||
41 | "type": "github" | ||
42 | } | ||
43 | }, | ||
44 | "nixpkgs": { | ||
45 | "locked": { | ||
46 | "lastModified": 1642069818, | ||
47 | "narHash": "sha256-666w6j8wl/bojfgpp0k58/UJ5rbrdYFbI2RFT2BXbSQ=", | ||
48 | "owner": "nixos", | ||
49 | "repo": "nixpkgs", | ||
50 | "rev": "46821ea01c8f54d2a20f5a503809abfc605269d7", | ||
51 | "type": "github" | ||
52 | }, | ||
53 | "original": { | ||
54 | "owner": "nixos", | ||
55 | "ref": "nixpkgs-unstable", | ||
56 | "repo": "nixpkgs", | ||
57 | "type": "github" | ||
58 | } | ||
59 | }, | ||
60 | "root": { | ||
61 | "inputs": { | ||
62 | "fenix": "fenix", | ||
63 | "gitignore": "gitignore", | ||
64 | "nixpkgs": "nixpkgs" | ||
65 | } | ||
66 | }, | ||
67 | "rust-analyzer-src": { | ||
68 | "flake": false, | ||
69 | "locked": { | ||
70 | "lastModified": 1642101527, | ||
71 | "narHash": "sha256-C4zcaWULWlrirpEt/pA85CCMBt+7SWZweMaMJ7EvrXw=", | ||
72 | "owner": "rust-analyzer", | ||
73 | "repo": "rust-analyzer", | ||
74 | "rev": "b4c31481a554d0132003228ba319bd9476fe85ae", | ||
75 | "type": "github" | ||
76 | }, | ||
77 | "original": { | ||
78 | "owner": "rust-analyzer", | ||
79 | "ref": "nightly", | ||
80 | "repo": "rust-analyzer", | ||
81 | "type": "github" | ||
82 | } | ||
83 | } | ||
84 | }, | ||
85 | "root": "root", | ||
86 | "version": 7 | ||
87 | } | ||
diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..3f416a9 --- /dev/null +++ b/flake.nix | |||
@@ -0,0 +1,101 @@ | |||
1 | { | ||
2 | inputs = { | ||
3 | |||
4 | nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; | ||
5 | |||
6 | fenix = { | ||
7 | url = "github:nix-community/fenix"; | ||
8 | inputs.nixpkgs.follows = "nixpkgs"; | ||
9 | }; | ||
10 | |||
11 | gitignore = { | ||
12 | url = "github:hercules-ci/gitignore.nix"; | ||
13 | inputs.nixpkgs.follows = "nixpkgs"; | ||
14 | }; | ||
15 | |||
16 | }; | ||
17 | |||
18 | outputs = | ||
19 | { self | ||
20 | , nixpkgs | ||
21 | , fenix | ||
22 | , gitignore | ||
23 | }: | ||
24 | let | ||
25 | inherit (gitignore.lib) gitignoreSource; | ||
26 | |||
27 | supportedSystems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ]; | ||
28 | forAllSystems = nixpkgs.lib.genAttrs supportedSystems; | ||
29 | nixpkgsFor = forAllSystems (system: | ||
30 | import nixpkgs { | ||
31 | inherit system; | ||
32 | overlays = [ self.overlay ]; | ||
33 | }); | ||
34 | |||
35 | chanspec = { | ||
36 | date = "2021-12-01"; | ||
37 | channel = "nightly"; | ||
38 | sha256 = "DhIP1w63/hMbWlgElJGBumEK/ExFWCdLaeBV5F8uWHc="; # set zeros after modifying channel or date | ||
39 | }; | ||
40 | rustChannel = p: (fenix.overlay p p).fenix.toolchainOf chanspec; | ||
41 | |||
42 | in | ||
43 | { | ||
44 | |||
45 | overlay = final: prev: { | ||
46 | |||
47 | prompt = with final; | ||
48 | let | ||
49 | pname = "prompt"; | ||
50 | packageMeta = (lib.importTOML ./bin/Cargo.toml).package; | ||
51 | rustPlatform = makeRustPlatform { | ||
52 | inherit (rustChannel final) cargo rustc; | ||
53 | }; | ||
54 | in | ||
55 | rustPlatform.buildRustPackage { | ||
56 | inherit pname; | ||
57 | inherit (packageMeta) version; | ||
58 | |||
59 | buildInputs = [ | ||
60 | final.openssl | ||
61 | final.pkgconfig | ||
62 | ]; | ||
63 | |||
64 | src = gitignoreSource ./.; | ||
65 | cargoLock.lockFile = ./Cargo.lock; | ||
66 | }; | ||
67 | |||
68 | }; | ||
69 | |||
70 | packages = forAllSystems (system: { | ||
71 | inherit (nixpkgsFor."${system}") prompt; | ||
72 | }); | ||
73 | |||
74 | defaultPackage = | ||
75 | forAllSystems (system: self.packages."${system}".prompt); | ||
76 | |||
77 | devShell = forAllSystems (system: | ||
78 | let | ||
79 | pkgs = nixpkgsFor."${system}"; | ||
80 | toolchain = (rustChannel pkgs).withComponents [ | ||
81 | "rustc" | ||
82 | "cargo" | ||
83 | "rust-std" | ||
84 | "rustfmt" | ||
85 | "clippy" | ||
86 | "rust-src" | ||
87 | ]; | ||
88 | inherit (fenix.packages."${system}") rust-analyzer; | ||
89 | in | ||
90 | pkgs.mkShell { | ||
91 | nativeBuildInputs = [ | ||
92 | pkgs.bacon | ||
93 | rust-analyzer | ||
94 | toolchain | ||
95 | ]; | ||
96 | RUST_LOG = "info"; | ||
97 | RUST_BACKTRACE = 1; | ||
98 | }); | ||
99 | |||
100 | }; | ||
101 | } | ||
diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..0b1ec1b --- /dev/null +++ b/src/main.rs | |||
@@ -0,0 +1,183 @@ | |||
1 | use std::{env, fmt, path::Path}; | ||
2 | |||
3 | use git2::{Oid, Repository, Status}; | ||
4 | use tico::tico; | ||
5 | |||
6 | fn main() { | ||
7 | let args = env::args().collect::<Vec<_>>(); | ||
8 | match args | ||
9 | .iter() | ||
10 | .map(String::as_str) | ||
11 | .collect::<Vec<&str>>() | ||
12 | .as_slice() | ||
13 | { | ||
14 | [_, "cwd", target] => print!("{}", cwd(target)), | ||
15 | [_, "vcs", target] => { | ||
16 | if let Some(status) = vcs(target) { | ||
17 | print!("{}", status) | ||
18 | } | ||
19 | } | ||
20 | _ => (), | ||
21 | } | ||
22 | } | ||
23 | |||
24 | fn cwd(target: &str) -> String { | ||
25 | let home = env::var("HOME").unwrap(); | ||
26 | |||
27 | let home_dir_ext = format!("{}{}", home, "/"); | ||
28 | if target == home.as_str() || target.starts_with(&home_dir_ext) { | ||
29 | let replaced = target.replacen(home.as_str(), "~", 1); | ||
30 | tico(&replaced) | ||
31 | } else { | ||
32 | tico(&target) | ||
33 | } | ||
34 | } | ||
35 | |||
36 | struct VcsStatus { | ||
37 | branch: Branch, | ||
38 | dist: Dist, | ||
39 | status: StatusSummary, | ||
40 | } | ||
41 | |||
42 | impl fmt::Display for VcsStatus { | ||
43 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
44 | write!( | ||
45 | f, | ||
46 | "{}{}{}#[fg=colour7]", | ||
47 | self.branch, self.dist, self.status | ||
48 | ) | ||
49 | } | ||
50 | } | ||
51 | |||
52 | enum Branch { | ||
53 | Id(Oid), | ||
54 | Ref(String), | ||
55 | Unknown, | ||
56 | } | ||
57 | |||
58 | impl fmt::Display for Branch { | ||
59 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
60 | match self { | ||
61 | Branch::Id(id) => write!(f, "#[fg=colour3]{:.7} ", id), | ||
62 | Branch::Ref(s) => write!(f, "#[fg=colour8]{} ", s), | ||
63 | Branch::Unknown => write!(f, ""), | ||
64 | } | ||
65 | } | ||
66 | } | ||
67 | |||
68 | enum Dist { | ||
69 | Ahead, | ||
70 | Behind, | ||
71 | Both, | ||
72 | Neither, | ||
73 | } | ||
74 | |||
75 | impl fmt::Display for Dist { | ||
76 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
77 | write!( | ||
78 | f, | ||
79 | "#[fg=colour8]{}", | ||
80 | match self { | ||
81 | Self::Ahead => "↑ ", | ||
82 | Self::Behind => "↓ ", | ||
83 | Self::Both => "↑↓ ", | ||
84 | Self::Neither => "", | ||
85 | } | ||
86 | ) | ||
87 | } | ||
88 | } | ||
89 | |||
90 | enum StatusSummary { | ||
91 | WtModified, | ||
92 | IdxModified, | ||
93 | Conflict, | ||
94 | Clean, | ||
95 | } | ||
96 | |||
97 | impl fmt::Display for StatusSummary { | ||
98 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
99 | write!( | ||
100 | f, | ||
101 | "{}", | ||
102 | match self { | ||
103 | Self::WtModified => "#[fg=colour1]×", | ||
104 | Self::IdxModified => "#[fg=colour3]±", | ||
105 | Self::Conflict => "#[fg=colour5]!", | ||
106 | Self::Clean => "#[fg=colour2]·", | ||
107 | } | ||
108 | ) | ||
109 | } | ||
110 | } | ||
111 | |||
112 | fn vcs(target: &str) -> Option<VcsStatus> { | ||
113 | let repo = match Path::new(target) | ||
114 | .ancestors() | ||
115 | .map(Repository::open) | ||
116 | .find_map(|r| r.ok()) | ||
117 | { | ||
118 | Some(r) => r, | ||
119 | None => return None, | ||
120 | }; | ||
121 | |||
122 | let dist = match get_ahead_behind(&repo) { | ||
123 | Some((ahead, behind)) if ahead > 0 && behind > 0 => Dist::Both, | ||
124 | Some((ahead, _)) if ahead > 0 => Dist::Ahead, | ||
125 | Some((_, behind)) if behind > 0 => Dist::Behind, | ||
126 | _ => Dist::Neither, | ||
127 | }; | ||
128 | |||
129 | let branch = match repo.head() { | ||
130 | Ok(reference) if reference.is_branch() => { | ||
131 | Branch::Ref(reference.shorthand().unwrap().to_string()) | ||
132 | } | ||
133 | Ok(reference) => Branch::Id(reference.peel_to_commit().unwrap().id()), | ||
134 | _ => Branch::Unknown, | ||
135 | }; | ||
136 | |||
137 | let status = repo_status(&repo); | ||
138 | |||
139 | Some(VcsStatus { | ||
140 | branch, | ||
141 | dist, | ||
142 | status, | ||
143 | }) | ||
144 | } | ||
145 | |||
146 | fn repo_status(repo: &Repository) -> StatusSummary { | ||
147 | for file in repo.statuses(None).unwrap().iter() { | ||
148 | match file.status() { | ||
149 | // STATE: conflicted | ||
150 | Status::CONFLICTED => return StatusSummary::Conflict, | ||
151 | // STATE: unstaged (working tree modified) | ||
152 | Status::WT_NEW | ||
153 | | Status::WT_MODIFIED | ||
154 | | Status::WT_DELETED | ||
155 | | Status::WT_TYPECHANGE | ||
156 | | Status::WT_RENAMED => return StatusSummary::WtModified, | ||
157 | // STATE: staged (changes added to index) | ||
158 | Status::INDEX_NEW | ||
159 | | Status::INDEX_MODIFIED | ||
160 | | Status::INDEX_DELETED | ||
161 | | Status::INDEX_TYPECHANGE | ||
162 | | Status::INDEX_RENAMED => return StatusSummary::IdxModified, | ||
163 | // STATE: committed (changes have been saved in the repo) | ||
164 | _ => return StatusSummary::Clean, | ||
165 | } | ||
166 | } | ||
167 | StatusSummary::Clean | ||
168 | } | ||
169 | |||
170 | fn get_ahead_behind(r: &Repository) -> Option<(usize, usize)> { | ||
171 | let head = (r.head().ok())?; | ||
172 | if !head.is_branch() { | ||
173 | return None; | ||
174 | } | ||
175 | |||
176 | let head_name = head.shorthand()?; | ||
177 | let head_branch = r.find_branch(head_name, git2::BranchType::Local).ok()?; | ||
178 | let upstream = head_branch.upstream().ok()?; | ||
179 | let head_oid = head.target()?; | ||
180 | let upstream_oid = upstream.get().target()?; | ||
181 | |||
182 | r.graph_ahead_behind(head_oid, upstream_oid).ok() | ||
183 | } | ||