1pub mod blame;
2pub mod commit;
3mod hosting_provider;
4mod remote;
5pub mod repository;
6pub mod status;
7
8pub use crate::hosting_provider::*;
9pub use crate::remote::*;
10use anyhow::{Context as _, Result};
11pub use git2 as libgit;
12use gpui::{Action, actions};
13pub use repository::WORK_DIRECTORY_REPO_PATH;
14use schemars::JsonSchema;
15use serde::{Deserialize, Serialize};
16use std::ffi::OsStr;
17use std::fmt;
18use std::str::FromStr;
19use std::sync::LazyLock;
20
21pub static DOT_GIT: LazyLock<&'static OsStr> = LazyLock::new(|| OsStr::new(".git"));
22pub static GITIGNORE: LazyLock<&'static OsStr> = LazyLock::new(|| OsStr::new(".gitignore"));
23pub static FSMONITOR_DAEMON: LazyLock<&'static OsStr> =
24 LazyLock::new(|| OsStr::new("fsmonitor--daemon"));
25pub static LFS_DIR: LazyLock<&'static OsStr> = LazyLock::new(|| OsStr::new("lfs"));
26pub static COMMIT_MESSAGE: LazyLock<&'static OsStr> =
27 LazyLock::new(|| OsStr::new("COMMIT_EDITMSG"));
28pub static INDEX_LOCK: LazyLock<&'static OsStr> = LazyLock::new(|| OsStr::new("index.lock"));
29
30actions!(
31 git,
32 [
33 // per-hunk
34 ToggleStaged,
35 StageAndNext,
36 UnstageAndNext,
37 #[action(deprecated_aliases = ["editor::RevertSelectedHunks"])]
38 Restore,
39 // per-file
40 #[action(deprecated_aliases = ["editor::ToggleGitBlame"])]
41 Blame,
42 StageFile,
43 UnstageFile,
44 // repo-wide
45 StageAll,
46 UnstageAll,
47 RestoreTrackedFiles,
48 TrashUntrackedFiles,
49 Uncommit,
50 Push,
51 PushTo,
52 ForcePush,
53 Pull,
54 Fetch,
55 FetchFrom,
56 Commit,
57 Amend,
58 Cancel,
59 ExpandCommitEditor,
60 GenerateCommitMessage,
61 Init,
62 OpenModifiedFiles,
63 ]
64);
65
66#[derive(Clone, Debug, Default, PartialEq, Deserialize, JsonSchema, Action)]
67#[action(namespace = git, deprecated_aliases = ["editor::RevertFile"])]
68pub struct RestoreFile {
69 #[serde(default)]
70 pub skip_prompt: bool,
71}
72
73/// The length of a Git short SHA.
74pub const SHORT_SHA_LENGTH: usize = 7;
75
76#[derive(Clone, Copy, Eq, Hash, PartialEq)]
77pub struct Oid(libgit::Oid);
78
79impl Oid {
80 pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
81 let oid = libgit::Oid::from_bytes(bytes).context("failed to parse bytes into git oid")?;
82 Ok(Self(oid))
83 }
84
85 pub fn as_bytes(&self) -> &[u8] {
86 self.0.as_bytes()
87 }
88
89 pub(crate) fn is_zero(&self) -> bool {
90 self.0.is_zero()
91 }
92
93 /// Returns this [`Oid`] as a short SHA.
94 pub fn display_short(&self) -> String {
95 self.to_string().chars().take(SHORT_SHA_LENGTH).collect()
96 }
97}
98
99impl FromStr for Oid {
100 type Err = anyhow::Error;
101
102 fn from_str(s: &str) -> std::prelude::v1::Result<Self, Self::Err> {
103 libgit::Oid::from_str(s)
104 .context("parsing git oid")
105 .map(Self)
106 }
107}
108
109impl fmt::Debug for Oid {
110 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111 fmt::Display::fmt(self, f)
112 }
113}
114
115impl fmt::Display for Oid {
116 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
117 self.0.fmt(f)
118 }
119}
120
121impl Serialize for Oid {
122 fn serialize<S>(&self, serializer: S) -> std::prelude::v1::Result<S::Ok, S::Error>
123 where
124 S: serde::Serializer,
125 {
126 serializer.serialize_str(&self.0.to_string())
127 }
128}
129
130impl<'de> Deserialize<'de> for Oid {
131 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
132 where
133 D: serde::Deserializer<'de>,
134 {
135 let s = String::deserialize(deserializer)?;
136 s.parse::<Oid>().map_err(serde::de::Error::custom)
137 }
138}
139
140impl Default for Oid {
141 fn default() -> Self {
142 Self(libgit::Oid::zero())
143 }
144}
145
146impl From<Oid> for u32 {
147 fn from(oid: Oid) -> Self {
148 let bytes = oid.0.as_bytes();
149 debug_assert!(bytes.len() > 4);
150
151 let mut u32_bytes: [u8; 4] = [0; 4];
152 u32_bytes.copy_from_slice(&bytes[..4]);
153
154 u32::from_ne_bytes(u32_bytes)
155 }
156}
157
158impl From<Oid> for usize {
159 fn from(oid: Oid) -> Self {
160 let bytes = oid.0.as_bytes();
161 debug_assert!(bytes.len() > 8);
162
163 let mut u64_bytes: [u8; 8] = [0; 8];
164 u64_bytes.copy_from_slice(&bytes[..8]);
165
166 u64::from_ne_bytes(u64_bytes) as usize
167 }
168}