Skip to content

Commit 94750e1

Browse files
committed
Merge branch 'adjustments-for-cargo'
2 parents f50b9f5 + 5979503 commit 94750e1

File tree

21 files changed

+333
-81
lines changed

21 files changed

+333
-81
lines changed

git-discover/src/is.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::{DOT_GIT_DIR, MODULES};
77
/// Please note that repositories without an index generally _look_ bare, even though they might also be uninitialized.
88
pub fn bare(git_dir_candidate: impl AsRef<Path>) -> bool {
99
let git_dir = git_dir_candidate.as_ref();
10-
!(git_dir.join("index").exists() || (git_dir.file_name() == Some(OsStr::new(DOT_GIT_DIR)) && git_dir.is_file()))
10+
!(git_dir.join("index").exists() || (git_dir.file_name() == Some(OsStr::new(DOT_GIT_DIR))))
1111
}
1212

1313
/// Returns true if `git_dir` is is located within a `.git/modules` directory, indicating it's a submodule clone.
@@ -130,7 +130,6 @@ pub fn git(git_dir: impl AsRef<Path>) -> Result<crate::repository::Kind, crate::
130130
return Err(crate::is_git::Error::MissingRefsDirectory { missing: refs_path });
131131
}
132132
}
133-
134133
Ok(match kind {
135134
Kind::LinkedWorkTreeDir => crate::repository::Kind::WorkTree {
136135
linked_git_dir: Some(dot_git.into_owned()),

git-discover/tests/fixtures/make_basic_repo.sh

+21
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,24 @@ rm -R worktrees/c-worktree-deleted
2626
git worktree add ../worktrees/from-bare/d-private-dir-deleted
2727
rm -R -v ./worktrees/d-private-dir-deleted
2828
)
29+
30+
git clone --bare --shared . bare-no-config.git
31+
(cd bare-no-config.git
32+
rm config
33+
)
34+
35+
git init --bare bare-no-config-after-init.git
36+
(cd bare-no-config-after-init.git
37+
rm config
38+
)
39+
40+
git clone --shared . worktree-no-config
41+
(cd worktree-no-config
42+
rm .git/config
43+
)
44+
45+
git init worktree-no-config-after-init
46+
(cd worktree-no-config-after-init
47+
rm .git/config
48+
)
49+

git-discover/tests/is_git/mod.rs

+22
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use crate::upwards::repo_path;
2+
13
#[cfg(target_os = "macos")]
24
#[test]
35
fn verify_on_exfat() -> crate::Result<()> {
@@ -37,3 +39,23 @@ fn verify_on_exfat() -> crate::Result<()> {
3739
);
3840
Ok(())
3941
}
42+
43+
#[test]
44+
fn missing_configuration_file_is_not_a_dealbreaker_in_bare_repo() -> crate::Result {
45+
for name in ["bare-no-config-after-init.git", "bare-no-config.git"] {
46+
let repo = repo_path()?.join(name);
47+
let kind = git_discover::is_git(repo)?;
48+
assert_eq!(kind, git_discover::repository::Kind::Bare);
49+
}
50+
Ok(())
51+
}
52+
53+
#[test]
54+
fn missing_configuration_file_is_not_a_dealbreaker_in_nonbare_repo() -> crate::Result {
55+
for name in ["worktree-no-config-after-init/.git", "worktree-no-config/.git"] {
56+
let repo = repo_path()?.join(name);
57+
let kind = git_discover::is_git(&repo)?;
58+
assert_eq!(kind, git_discover::repository::Kind::WorkTree { linked_git_dir: None });
59+
}
60+
Ok(())
61+
}

git-discover/tests/upwards/mod.rs

+25-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,18 @@ fn from_bare_git_dir() -> crate::Result {
2222
Ok(())
2323
}
2424

25+
#[test]
26+
fn from_bare_git_dir_without_config_file() -> crate::Result {
27+
for name in ["bare-no-config.git", "bare-no-config-after-init.git"] {
28+
let dir = repo_path()?.join(name);
29+
let (path, trust) = git_discover::upwards(&dir)?;
30+
assert_eq!(path.as_ref(), dir, "the bare .git dir is directly returned");
31+
assert_eq!(path.kind(), Kind::Bare);
32+
assert_eq!(trust, expected_trust());
33+
}
34+
Ok(())
35+
}
36+
2537
#[test]
2638
fn from_inside_bare_git_dir() -> crate::Result {
2739
let git_dir = repo_path()?.join("bare.git");
@@ -61,6 +73,18 @@ fn from_working_dir() -> crate::Result {
6173
Ok(())
6274
}
6375

76+
#[test]
77+
fn from_working_dir_no_config() -> crate::Result {
78+
for name in ["worktree-no-config-after-init", "worktree-no-config"] {
79+
let dir = repo_path()?.join(name);
80+
let (path, trust) = git_discover::upwards(&dir)?;
81+
assert_eq!(path.kind(), Kind::WorkTree { linked_git_dir: None },);
82+
assert_eq!(path.as_ref(), dir, "a working tree dir yields the git dir");
83+
assert_eq!(trust, expected_trust());
84+
}
85+
Ok(())
86+
}
87+
6488
#[test]
6589
fn from_nested_dir() -> crate::Result {
6690
let working_dir = repo_path()?;
@@ -328,6 +352,6 @@ mod submodules {
328352
}
329353
}
330354

331-
fn repo_path() -> crate::Result<PathBuf> {
355+
pub(crate) fn repo_path() -> crate::Result<PathBuf> {
332356
git_testtools::scripted_fixture_repo_read_only("make_basic_repo.sh")
333357
}

git-protocol/src/handshake/function.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,10 @@ where
4242
Ok(v) => Ok(v),
4343
Err(client::Error::Io(ref err)) if err.kind() == std::io::ErrorKind::PermissionDenied => {
4444
drop(result); // needed to workaround this: https://github.com/rust-lang/rust/issues/76149
45-
let url = transport.to_url();
45+
let url = transport.to_url().into_owned();
4646
progress.set_name("authentication");
4747
let credentials::protocol::Outcome { identity, next } =
48-
authenticate(credentials::helper::Action::get_for_url(url.into_owned()))?
48+
authenticate(credentials::helper::Action::get_for_url(url.clone()))?
4949
.expect("FILL provides an identity or errors");
5050
transport.set_identity(identity)?;
5151
progress.step();
@@ -58,7 +58,7 @@ where
5858
// Still no permission? Reject the credentials.
5959
Err(client::Error::Io(err)) if err.kind() == std::io::ErrorKind::PermissionDenied => {
6060
authenticate(next.erase())?;
61-
Err(client::Error::Io(err))
61+
return Err(Error::InvalidCredentials { url });
6262
}
6363
// Otherwise, do nothing, as we don't know if it actually got to try the credentials.
6464
// If they were previously stored, they remain. In the worst case, the user has to enter them again

git-protocol/src/handshake/mod.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ pub struct Outcome {
5757
}
5858

5959
mod error {
60+
use bstr::BString;
6061
use git_transport::client;
6162

6263
use crate::{credentials, handshake::refs};
@@ -65,8 +66,10 @@ mod error {
6566
#[derive(Debug, thiserror::Error)]
6667
#[allow(missing_docs)]
6768
pub enum Error {
68-
#[error(transparent)]
69+
#[error("Failed to obtain credentials")]
6970
Credentials(#[from] credentials::protocol::Error),
71+
#[error("Credentials provided for \"{url}\" were not accepted by the remote")]
72+
InvalidCredentials { url: BString },
7073
#[error(transparent)]
7174
Transport(#[from] client::Error),
7275
#[error("The transport didn't accept the advertised server version {actual_version:?} and closed the connection client side")]

git-repository/src/config/cache/incubate.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ impl StageOne {
3030
lossy,
3131
)?;
3232

33-
let is_bare = util::config_bool(&config, "core.bare", false, lenient)?;
33+
// Note that we assume the repo is bare by default unless we are told otherwise. This is relevant if
34+
// the repo doesn't have a configuration file.
35+
let is_bare = util::config_bool(&config, "core.bare", true, lenient)?;
3436
let repo_format_version = config
3537
.value::<git_config::Integer>("core", None, "repositoryFormatVersion")
3638
.map_or(0, |v| v.to_decimal().unwrap_or_default());
@@ -82,7 +84,12 @@ fn load_config(
8284
lossy: Option<bool>,
8385
) -> Result<git_config::File<'static>, Error> {
8486
buf.clear();
85-
std::io::copy(&mut std::fs::File::open(&config_path)?, buf)?;
87+
let mut file = match std::fs::File::open(&config_path) {
88+
Ok(f) => f,
89+
Err(err) if err.kind() == std::io::ErrorKind::NotFound => return Ok(git_config::File::default()),
90+
Err(err) => return Err(err.into()),
91+
};
92+
std::io::copy(&mut file, buf)?;
8693

8794
let config = git_config::File::from_bytes_owned(
8895
buf,

git-repository/src/config/cache/init.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ impl Cache {
9090
"HOME" => Some(home_env),
9191
_ => None,
9292
}
93-
.and_then(|perm| std::env::var_os(name).and_then(|val| perm.check_opt(val)))
93+
.and_then(|perm| perm.check_opt(name).and_then(std::env::var_os))
9494
})
9595
.map(|p| (source, p.into_owned()))
9696
})

git-repository/src/open/mod.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,11 @@ pub struct Options {
3333
pub enum Error {
3434
#[error("Failed to load the git configuration")]
3535
Config(#[from] config::Error),
36-
#[error(transparent)]
37-
NotARepository(#[from] git_discover::is_git::Error),
36+
#[error("\"{path}\" does not appear to be a git repository")]
37+
NotARepository {
38+
source: git_discover::is_git::Error,
39+
path: PathBuf,
40+
},
3841
#[error(transparent)]
3942
Io(#[from] std::io::Error),
4043
#[error("The git directory at '{}' is considered unsafe as it's not owned by the current user.", .path.display())]

git-repository/src/open/repository.rs

+15-3
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ impl ThreadSafeRepository {
5252
Ok(kind) => (path, kind),
5353
Err(_err) => {
5454
let git_dir = path.join(git_discover::DOT_GIT_DIR);
55-
git_discover::is_git(&git_dir).map(|kind| (git_dir, kind))?
55+
git_discover::is_git(&git_dir)
56+
.map(|kind| (git_dir, kind))
57+
.map_err(|err| Error::NotARepository { source: err, path })?
5658
}
5759
}
5860
};
@@ -85,10 +87,20 @@ impl ThreadSafeRepository {
8587
) -> Result<Self, Error> {
8688
let overrides = EnvironmentOverrides::from_env()?;
8789
let (path, path_kind): (PathBuf, _) = match overrides.git_dir {
88-
Some(git_dir) => git_discover::is_git(&git_dir).map(|kind| (git_dir, kind))?,
90+
Some(git_dir) => git_discover::is_git(&git_dir)
91+
.map_err(|err| Error::NotARepository {
92+
source: err,
93+
path: git_dir.clone(),
94+
})
95+
.map(|kind| (git_dir, kind))?,
8996
None => {
9097
let fallback_directory = fallback_directory.into();
91-
git_discover::is_git(&fallback_directory).map(|kind| (fallback_directory, kind))?
98+
git_discover::is_git(&fallback_directory)
99+
.map_err(|err| Error::NotARepository {
100+
source: err,
101+
path: fallback_directory.clone(),
102+
})
103+
.map(|kind| (fallback_directory, kind))?
92104
}
93105
};
94106

git-repository/src/remote/connection/access.rs

+4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ impl<'a, 'repo, T, P> Connection<'a, 'repo, T, P> {
1212
/// user.
1313
///
1414
/// A custom function may also be used to prevent accessing resources with authentication.
15+
///
16+
/// Use the [configured_credentials()][Connection::configured_credentials()] method to obtain the implementation
17+
/// that would otherwise be used, which can be useful to proxy the default configuration and obtain information about the
18+
/// URLs to authenticate with.
1519
pub fn with_credentials(
1620
mut self,
1721
helper: impl FnMut(git_credentials::helper::Action) -> git_credentials::protocol::Result + 'a,

git-repository/src/repository/worktree.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ impl crate::Repository {
5050
/// This is not to be confused with the [`worktree()`][crate::Repository::worktree()] worktree, which may exists if this instance
5151
/// was opened in a worktree that was created separately.
5252
pub fn is_bare(&self) -> bool {
53-
self.config.is_bare
53+
self.config.is_bare && self.work_dir().is_none()
5454
}
5555

5656
/// Open a new copy of the index file and decode it entirely.
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
version https://git-lfs.github.com/spec/v1
2-
oid sha256:3d893d90b1870819d92b25f84214d10e7565f6cab71032959659f284642dc5a4
3-
size 13808
2+
oid sha256:f90e312e56b67e6da1596b444bb4a266238b28b7ca6744b59f650ab86ec195fa
3+
size 14404

git-repository/tests/fixtures/make_config_repos.sh

+18
Original file line numberDiff line numberDiff line change
@@ -111,3 +111,21 @@ git init disabled-object-caches
111111
git config core.deltaBaseCacheLimit 0
112112
git config gitoxide.objects.cacheLimit 0
113113
)
114+
115+
git init --bare bare-no-config
116+
(cd bare-no-config
117+
rm config
118+
git config -l >/dev/null
119+
)
120+
121+
git init worktree-no-config
122+
(cd worktree-no-config
123+
rm .git/config
124+
git config -l >/dev/null
125+
)
126+
127+
mkdir not-a-repo-empty-dir;
128+
mkdir not-a-repo-with-files;
129+
(cd not-a-repo-with-files
130+
touch this that
131+
)

git-repository/tests/repository/open.rs

+48
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,51 @@
1+
mod missing_config_file {
2+
use crate::util::named_subrepo_opts;
3+
use git_repository as git;
4+
5+
#[test]
6+
fn bare() -> crate::Result {
7+
let repo = named_subrepo_opts("make_config_repos.sh", "bare-no-config", git::open::Options::isolated())?;
8+
assert!(
9+
repo.is_bare(),
10+
"without config, we can't really know what the repo is actually but can guess by not having a worktree"
11+
);
12+
assert_eq!(repo.work_dir(), None);
13+
assert!(repo.worktree().is_none());
14+
Ok(())
15+
}
16+
17+
#[test]
18+
fn non_bare() -> crate::Result {
19+
let repo = named_subrepo_opts(
20+
"make_config_repos.sh",
21+
"worktree-no-config",
22+
git::open::Options::isolated(),
23+
)?;
24+
assert!(repo.work_dir().is_some());
25+
assert!(repo.worktree().is_some());
26+
assert!(
27+
!repo.is_bare(),
28+
"without config, we can't really know what the repo is actually but can guess as there is a worktree"
29+
);
30+
Ok(())
31+
}
32+
}
33+
34+
mod not_a_repository {
35+
use git_repository as git;
36+
37+
#[test]
38+
fn shows_proper_error() -> crate::Result {
39+
for name in ["empty-dir", "with-files"] {
40+
let name = format!("not-a-repo-{name}");
41+
let repo_path = git_testtools::scripted_fixture_repo_read_only("make_config_repos.sh")?.join(name);
42+
let err = git::open_opts(&repo_path, git::open::Options::isolated()).unwrap_err();
43+
assert!(matches!(err, git::open::Error::NotARepository { path, .. } if path == repo_path));
44+
}
45+
Ok(())
46+
}
47+
}
48+
149
mod submodules {
250
use std::path::Path;
351

git-transport/src/client/blocking_io/http/curl/mod.rs

+14-12
Original file line numberDiff line numberDiff line change
@@ -22,23 +22,25 @@ pub enum Error {
2222
impl crate::IsSpuriousError for Error {
2323
fn is_spurious(&self) -> bool {
2424
match self {
25-
Error::Curl(err) => {
26-
err.is_couldnt_connect()
27-
|| err.is_couldnt_resolve_proxy()
28-
|| err.is_couldnt_resolve_host()
29-
|| err.is_operation_timedout()
30-
|| err.is_recv_error()
31-
|| err.is_send_error()
32-
|| err.is_http2_error()
33-
|| err.is_http2_stream_error()
34-
|| err.is_ssl_connect_error()
35-
|| err.is_partial_file()
36-
}
25+
Error::Curl(err) => curl_is_spurious(err),
3726
_ => false,
3827
}
3928
}
4029
}
4130

31+
pub fn curl_is_spurious(err: &curl::Error) -> bool {
32+
err.is_couldnt_connect()
33+
|| err.is_couldnt_resolve_proxy()
34+
|| err.is_couldnt_resolve_host()
35+
|| err.is_operation_timedout()
36+
|| err.is_recv_error()
37+
|| err.is_send_error()
38+
|| err.is_http2_error()
39+
|| err.is_http2_stream_error()
40+
|| err.is_ssl_connect_error()
41+
|| err.is_partial_file()
42+
}
43+
4244
pub struct Curl {
4345
req: SyncSender<remote::Request>,
4446
res: Receiver<remote::Response>,

0 commit comments

Comments
 (0)