Skip to content

Commit efc8bf4

Browse files
committed
feat: Repository::is_shallow() to test if a repository is shallow.
1 parent cf620f8 commit efc8bf4

File tree

8 files changed

+112
-5
lines changed

8 files changed

+112
-5
lines changed

gix/src/config/cache/init.rs

+9
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,15 @@ fn apply_environment_overrides(
347347
},
348348
],
349349
),
350+
(
351+
"gitoxide",
352+
Some(Cow::Borrowed("core".into())),
353+
git_prefix,
354+
&[{
355+
let key = &gitoxide::Core::SHALLOW_FILE;
356+
(env(key), key.name)
357+
}],
358+
),
350359
(
351360
"gitoxide",
352361
Some(Cow::Borrowed("author".into())),

gix/src/config/tree/sections/gitoxide.rs

+25-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1+
use crate::config;
12
use crate::config::tree::{keys, Gitoxide, Key, Section};
23

34
impl Gitoxide {
45
/// The `gitoxide.allow` section.
56
pub const ALLOW: Allow = Allow;
67
/// The `gitoxide.author` section.
78
pub const AUTHOR: Author = Author;
9+
/// The `gitoxide.core` section.
10+
pub const CORE: Core = Core;
811
/// The `gitoxide.commit` section.
912
pub const COMMIT: Commit = Commit;
1013
/// The `gitoxide.committer` section.
@@ -39,6 +42,7 @@ impl Section for Gitoxide {
3942
&[
4043
&Self::ALLOW,
4144
&Self::AUTHOR,
45+
&Self::CORE,
4246
&Self::COMMIT,
4347
&Self::COMMITTER,
4448
&Self::HTTP,
@@ -56,6 +60,26 @@ mod subsections {
5660
Tree,
5761
};
5862

63+
/// The `Core` sub-section.
64+
#[derive(Copy, Clone, Default)]
65+
pub struct Core;
66+
67+
impl Core {
68+
/// The `gitoxide.core.shallowFile` key.
69+
pub const SHALLOW_FILE: keys::Path =
70+
keys::Path::new_path("shallowFile", &Gitoxide::CORE).with_environment_override("GIT_SHALLOW_FILE");
71+
}
72+
73+
impl Section for Core {
74+
fn name(&self) -> &str {
75+
"core"
76+
}
77+
78+
fn keys(&self) -> &[&dyn Key] {
79+
&[&Self::SHALLOW_FILE]
80+
}
81+
}
82+
5983
/// The `Http` sub-section.
6084
#[derive(Copy, Clone, Default)]
6185
pub struct Http;
@@ -341,6 +365,7 @@ mod subsections {
341365
}
342366
}
343367
}
368+
pub use subsections::{Allow, Author, Commit, Committer, Core, Http, Https, Objects, Ssh, User};
344369

345370
pub mod validate {
346371
use std::error::Error;
@@ -357,7 +382,3 @@ pub mod validate {
357382
}
358383
}
359384
}
360-
361-
pub use subsections::{Allow, Author, Commit, Committer, Http, Https, Objects, Ssh, User};
362-
363-
use crate::config;

gix/src/repository/location.rs

+16
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
use std::borrow::Cow;
12
use std::path::PathBuf;
23

4+
use crate::config::tree::{gitoxide, Key};
35
use gix_path::realpath::MAX_SYMLINKS;
46

57
impl crate::Repository {
@@ -41,6 +43,20 @@ impl crate::Repository {
4143
crate::path::install_dir()
4244
}
4345

46+
/// Return the path to the `shallow` file which contains hashes, one per line, that describe commits that don't have their
47+
/// parents within this repository.
48+
pub fn shallow_file(&self) -> PathBuf {
49+
let shallow_name = self
50+
.config
51+
.resolved
52+
.string_filter_by_key(
53+
gitoxide::Core::SHALLOW_FILE.logical_name().as_str(),
54+
&mut self.filter_config_section(),
55+
)
56+
.unwrap_or(Cow::Borrowed("shallow".into()));
57+
self.common_dir().join(gix_path::from_bstr(shallow_name))
58+
}
59+
4460
/// Returns the relative path which is the components between the working tree and the current working dir (CWD).
4561
/// Note that there may be `None` if there is no work tree, even though the `PathBuf` will be empty
4662
/// if the CWD is at the root of the work tree.

gix/src/repository/state.rs

+7
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,11 @@ impl crate::Repository {
4141
None
4242
}
4343
}
44+
45+
/// Return `true` if the repository is a shallow clone, i.e. contains history only up to a certain depth.
46+
pub fn is_shallow(&self) -> bool {
47+
self.shallow_file()
48+
.symlink_metadata()
49+
.map_or(false, |m| m.is_file() && m.len() > 0)
50+
}
4451
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:ebe6142b7fa52667ec7f3c5ab3efa646dc126903076c114600c2f66658426576
3+
size 12040
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/bin/bash
2+
set -eu -o pipefail
3+
4+
mkdir base
5+
(cd base
6+
git init -q
7+
8+
git checkout -b main
9+
touch a && git add a
10+
git commit -q -m c1
11+
echo 1 >> a
12+
git commit -q -am c2
13+
echo 1 >> a
14+
git commit -q -am c3
15+
)
16+
17+
git clone --depth 1 --bare file://$PWD/base shallow.git
18+
git clone --depth 1 file://$PWD/base shallow

gix/tests/repository/open.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,8 @@ mod with_overrides {
194194
.set("GIT_SSL_VERSION", "tlsv1.3")
195195
.set("GIT_SSH_VARIANT", "ssh-variant-env")
196196
.set("GIT_SSH_COMMAND", "ssh-command-env")
197-
.set("GIT_SSH", "ssh-command-fallback-env");
197+
.set("GIT_SSH", "ssh-command-fallback-env")
198+
.set("GIT_SHALLOW_FILE", "shallow-file-env");
198199
let mut opts = gix::open::Options::isolated()
199200
.cli_overrides([
200201
"http.userAgent=agent-from-cli",
@@ -206,6 +207,7 @@ mod with_overrides {
206207
"core.sshCommand=ssh-command-cli",
207208
"gitoxide.ssh.commandWithoutShellFallback=ssh-command-fallback-cli",
208209
"gitoxide.http.proxyAuthMethod=proxy-auth-method-cli",
210+
"gitoxide.core.shallowFile=shallow-file-cli",
209211
])
210212
.config_overrides([
211213
"http.userAgent=agent-from-api",
@@ -217,6 +219,7 @@ mod with_overrides {
217219
"core.sshCommand=ssh-command-api",
218220
"gitoxide.ssh.commandWithoutShellFallback=ssh-command-fallback-api",
219221
"gitoxide.http.proxyAuthMethod=proxy-auth-method-api",
222+
"gitoxide.core.shallowFile=shallow-file-api",
220223
]);
221224
opts.permissions.env.git_prefix = Permission::Allow;
222225
opts.permissions.env.http_transport = Permission::Allow;
@@ -229,6 +232,16 @@ mod with_overrides {
229232
"config always refers to the local one for safety"
230233
);
231234
let config = repo.config_snapshot();
235+
assert_eq!(
236+
config
237+
.strings_by_key("gitoxide.core.shallowFile")
238+
.expect("at least one value"),
239+
[
240+
cow_bstr("shallow-file-cli"),
241+
cow_bstr("shallow-file-api"),
242+
cow_bstr("shallow-file-env")
243+
]
244+
);
232245
assert_eq!(
233246
config.strings_by_key("http.userAgent").expect("at least one value"),
234247
[

gix/tests/repository/state.rs

+20
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,23 @@ fn revert_sequence() -> Result {
7777

7878
Ok(())
7979
}
80+
81+
mod shallow {
82+
use crate::util::named_subrepo_opts;
83+
84+
#[test]
85+
fn without() -> crate::Result {
86+
let repo = named_subrepo_opts("make_shallow_repo.sh", "base", gix::open::Options::isolated())?;
87+
assert!(!repo.is_shallow());
88+
Ok(())
89+
}
90+
91+
#[test]
92+
fn with() -> crate::Result {
93+
for name in ["shallow.git", "shallow"] {
94+
let repo = named_subrepo_opts("make_shallow_repo.sh", name, gix::open::Options::isolated())?;
95+
assert!(repo.is_shallow());
96+
}
97+
Ok(())
98+
}
99+
}

0 commit comments

Comments
 (0)