Skip to content

Commit 383a68e

Browse files
committed
Auto merge of #12197 - weihanglo:source-refactor, r=epage
refactor: git source cleanup
2 parents b8402be + 88845b9 commit 383a68e

File tree

2 files changed

+53
-50
lines changed

2 files changed

+53
-50
lines changed

Diff for: src/cargo/sources/git/source.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -279,8 +279,7 @@ impl<'cfg> Source for GitSource<'cfg> {
279279
.join("checkouts")
280280
.join(&self.ident)
281281
.join(short_id.as_str());
282-
let parent_remote_url = self.url();
283-
db.copy_to(actual_rev, &checkout_path, self.config, parent_remote_url)?;
282+
db.copy_to(actual_rev, &checkout_path, self.config)?;
284283

285284
let source_id = self.source_id.with_precise(Some(actual_rev.to_string()));
286285
let path_source = PathSource::new_recursive(&checkout_path, source_id, self.config);

Diff for: src/cargo/sources/git/utils.rs

+52-48
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ use std::sync::atomic::{AtomicBool, Ordering};
2323
use std::time::{Duration, Instant};
2424
use url::Url;
2525

26+
/// A file indicates that if present, `git reset` has been done and a repo
27+
/// checkout is ready to go. See [`GitCheckout::reset`] for why we need this.
28+
const CHECKOUT_READY_LOCK: &str = ".cargo-ok";
29+
2630
fn serialize_str<T, S>(t: &T, s: S) -> Result<S::Ok, S::Error>
2731
where
2832
T: fmt::Display,
@@ -53,29 +57,24 @@ pub struct GitRemote {
5357

5458
/// A local clone of a remote repository's database. Multiple [`GitCheckout`]s
5559
/// can be cloned from a single [`GitDatabase`].
56-
#[derive(Serialize)]
5760
pub struct GitDatabase {
5861
/// The remote repository where this database is fetched from.
5962
remote: GitRemote,
6063
/// Path to the root of the underlying Git repository on the local filesystem.
6164
path: PathBuf,
6265
/// Underlying Git repository instance for this database.
63-
#[serde(skip_serializing)]
6466
repo: git2::Repository,
6567
}
6668

6769
/// A local checkout of a particular revision from a [`GitDatabase`].
68-
#[derive(Serialize)]
6970
pub struct GitCheckout<'a> {
7071
/// The git database where this checkout is cloned from.
7172
database: &'a GitDatabase,
7273
/// Path to the root of the underlying Git repository on the local filesystem.
73-
location: PathBuf,
74+
path: PathBuf,
7475
/// The git revision this checkout is for.
75-
#[serde(serialize_with = "serialize_str")]
7676
revision: git2::Oid,
7777
/// Underlying Git repository instance for this checkout.
78-
#[serde(skip_serializing)]
7978
repo: git2::Repository,
8079
}
8180

@@ -90,10 +89,6 @@ impl GitRemote {
9089
&self.url
9190
}
9291

93-
pub fn rev_for(&self, path: &Path, reference: &GitReference) -> CargoResult<git2::Oid> {
94-
reference.resolve(&self.db_at(path)?.repo)
95-
}
96-
9792
/// Fetches and checkouts to a reference or a revision from this remote
9893
/// into a local path.
9994
///
@@ -184,21 +179,20 @@ impl GitDatabase {
184179
rev: git2::Oid,
185180
dest: &Path,
186181
cargo_config: &Config,
187-
parent_remote_url: &Url,
188182
) -> CargoResult<GitCheckout<'_>> {
189183
// If the existing checkout exists, and it is fresh, use it.
190184
// A non-fresh checkout can happen if the checkout operation was
191185
// interrupted. In that case, the checkout gets deleted and a new
192186
// clone is created.
193187
let checkout = match git2::Repository::open(dest)
194188
.ok()
195-
.map(|repo| GitCheckout::new(dest, self, rev, repo))
189+
.map(|repo| GitCheckout::new(self, rev, repo))
196190
.filter(|co| co.is_fresh())
197191
{
198192
Some(co) => co,
199193
None => GitCheckout::clone_into(dest, self, rev, cargo_config)?,
200194
};
201-
checkout.update_submodules(cargo_config, parent_remote_url)?;
195+
checkout.update_submodules(cargo_config)?;
202196
Ok(checkout)
203197
}
204198

@@ -270,21 +264,26 @@ impl<'a> GitCheckout<'a> {
270264
/// is done. Use [`GitCheckout::is_fresh`] to check.
271265
///
272266
/// * The `database` is where this checkout is from.
273-
/// * The `repo` will be the checked out Git repoistory at `path`.
267+
/// * The `repo` will be the checked out Git repoistory.
274268
fn new(
275-
path: &Path,
276269
database: &'a GitDatabase,
277270
revision: git2::Oid,
278271
repo: git2::Repository,
279272
) -> GitCheckout<'a> {
273+
let path = repo.workdir().unwrap_or_else(|| repo.path());
280274
GitCheckout {
281-
location: path.to_path_buf(),
275+
path: path.to_path_buf(),
282276
database,
283277
revision,
284278
repo,
285279
}
286280
}
287281

282+
/// Gets the remote repository URL.
283+
fn remote_url(&self) -> &Url {
284+
&self.database.remote.url()
285+
}
286+
288287
/// Clone a repo for a `revision` into a local path from a `datatabase`.
289288
/// This is a filesystem-to-filesystem clone.
290289
fn clone_into(
@@ -340,7 +339,7 @@ impl<'a> GitCheckout<'a> {
340339
})?;
341340
let repo = repo.unwrap();
342341

343-
let checkout = GitCheckout::new(into, database, revision, repo);
342+
let checkout = GitCheckout::new(database, revision, repo);
344343
checkout.reset(config)?;
345344
Ok(checkout)
346345
}
@@ -350,24 +349,28 @@ impl<'a> GitCheckout<'a> {
350349
match self.repo.revparse_single("HEAD") {
351350
Ok(ref head) if head.id() == self.revision => {
352351
// See comments in reset() for why we check this
353-
self.location.join(".cargo-ok").exists()
352+
self.path.join(CHECKOUT_READY_LOCK).exists()
354353
}
355354
_ => false,
356355
}
357356
}
358357

359-
/// `git reset --hard` to the revision of this checkout, with additional
360-
/// interrupt protection by a dummy `.cargo-ok` file.
358+
/// Similar to [`reset()`]. This roughly performs `git reset --hard` to the
359+
/// revision of this checkout, with additional interrupt protection by a
360+
/// dummy file [`CHECKOUT_READY_LOCK`].
361+
///
362+
/// If we're interrupted while performing a `git reset` (e.g., we die
363+
/// because of a signal) Cargo needs to be sure to try to check out this
364+
/// repo again on the next go-round.
365+
///
366+
/// To enable this we have a dummy file in our checkout, [`.cargo-ok`],
367+
/// which if present means that the repo has been successfully reset and is
368+
/// ready to go. Hence if we start to do a reset, we make sure this file
369+
/// *doesn't* exist, and then once we're done we create the file.
370+
///
371+
/// [`.cargo-ok`]: CHECKOUT_READY_LOCK
361372
fn reset(&self, config: &Config) -> CargoResult<()> {
362-
// If we're interrupted while performing this reset (e.g., we die because
363-
// of a signal) Cargo needs to be sure to try to check out this repo
364-
// again on the next go-round.
365-
//
366-
// To enable this we have a dummy file in our checkout, .cargo-ok, which
367-
// if present means that the repo has been successfully reset and is
368-
// ready to go. Hence if we start to do a reset, we make sure this file
369-
// *doesn't* exist, and then once we're done we create the file.
370-
let ok_file = self.location.join(".cargo-ok");
373+
let ok_file = self.path.join(CHECKOUT_READY_LOCK);
371374
let _ = paths::remove_file(&ok_file);
372375
info!("reset {} to {}", self.repo.path().display(), self.revision);
373376

@@ -388,8 +391,8 @@ impl<'a> GitCheckout<'a> {
388391
/// Submodules set to `none` won't be fetched.
389392
///
390393
/// [^1]: <https://git-scm.com/docs/git-submodule#Documentation/git-submodule.txt-none>
391-
fn update_submodules(&self, cargo_config: &Config, parent_remote_url: &Url) -> CargoResult<()> {
392-
return update_submodules(&self.repo, cargo_config, parent_remote_url);
394+
fn update_submodules(&self, cargo_config: &Config) -> CargoResult<()> {
395+
return update_submodules(&self.repo, cargo_config, self.remote_url());
393396

394397
/// Recusive helper for [`GitCheckout::update_submodules`].
395398
fn update_submodules(
@@ -892,13 +895,15 @@ pub fn with_fetch_options(
892895
/// * Turns [`GitReference`] into refspecs accordingly.
893896
/// * Dispatches `git fetch` using libgit2, gitoxide, or git CLI.
894897
///
895-
/// `remote_kind` is a thing for [`-Zgitoxide`] shallow clones at this time.
896-
/// It could be extended when libgit2 supports shallow clones.
898+
/// The `remote_url` argument is the git remote URL where we want to fetch from.
899+
///
900+
/// The `remote_kind` argument is a thing for [`-Zgitoxide`] shallow clones
901+
/// at this time. It could be extended when libgit2 supports shallow clones.
897902
///
898903
/// [`-Zgitoxide`]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#gitoxide
899904
pub fn fetch(
900905
repo: &mut git2::Repository,
901-
orig_url: &str,
906+
remote_url: &str,
902907
reference: &GitReference,
903908
config: &Config,
904909
remote_kind: RemoteKind,
@@ -915,7 +920,7 @@ pub fn fetch(
915920

916921
let shallow = remote_kind.to_shallow_setting(repo.is_shallow(), config);
917922

918-
let oid_to_fetch = match github_fast_path(repo, orig_url, reference, config) {
923+
let oid_to_fetch = match github_fast_path(repo, remote_url, reference, config) {
919924
Ok(FastPathRev::UpToDate) => return Ok(()),
920925
Ok(FastPathRev::NeedsFetch(rev)) => Some(rev),
921926
Ok(FastPathRev::Indeterminate) => None,
@@ -978,7 +983,7 @@ pub fn fetch(
978983
}
979984

980985
if let Some(true) = config.net_config()?.git_fetch_with_cli {
981-
return fetch_with_cli(repo, orig_url, &refspecs, tags, config);
986+
return fetch_with_cli(repo, remote_url, &refspecs, tags, config);
982987
}
983988

984989
if config
@@ -1014,10 +1019,10 @@ pub fn fetch(
10141019
)
10151020
.map_err(crate::sources::git::fetch::Error::from)
10161021
.and_then(|repo| {
1017-
debug!("initiating fetch of {:?} from {}", refspecs, orig_url);
1022+
debug!("initiating fetch of {refspecs:?} from {remote_url}");
10181023
let url_for_authentication = &mut *url_for_authentication;
10191024
let remote = repo
1020-
.remote_at(orig_url)?
1025+
.remote_at(remote_url)?
10211026
.with_fetch_tags(if tags {
10221027
gix::remote::fetch::Tags::All
10231028
} else {
@@ -1036,10 +1041,9 @@ pub fn fetch(
10361041
let mut authenticate = connection.configured_credentials(url)?;
10371042
let connection = connection.with_credentials(
10381043
move |action: gix::protocol::credentials::helper::Action| {
1039-
if let Some(url) = action
1040-
.context()
1041-
.and_then(|ctx| ctx.url.as_ref().filter(|url| *url != orig_url))
1042-
{
1044+
if let Some(url) = action.context().and_then(|ctx| {
1045+
ctx.url.as_ref().filter(|url| *url != remote_url)
1046+
}) {
10431047
url_for_authentication(url.as_ref());
10441048
}
10451049
authenticate(action)
@@ -1085,9 +1089,9 @@ pub fn fetch(
10851089
}
10861090
res
10871091
} else {
1088-
debug!("doing a fetch for {}", orig_url);
1092+
debug!("doing a fetch for {remote_url}");
10891093
let git_config = git2::Config::open_default()?;
1090-
with_fetch_options(&git_config, orig_url, config, &mut |mut opts| {
1094+
with_fetch_options(&git_config, remote_url, config, &mut |mut opts| {
10911095
if tags {
10921096
opts.download_tags(git2::AutotagOption::All);
10931097
}
@@ -1103,10 +1107,10 @@ pub fn fetch(
11031107
// blown away the repository, then we want to return the error as-is.
11041108
let mut repo_reinitialized = false;
11051109
loop {
1106-
debug!("initiating fetch of {:?} from {}", refspecs, orig_url);
1107-
let res = repo
1108-
.remote_anonymous(orig_url)?
1109-
.fetch(&refspecs, Some(&mut opts), None);
1110+
debug!("initiating fetch of {refspecs:?} from {remote_url}");
1111+
let res =
1112+
repo.remote_anonymous(remote_url)?
1113+
.fetch(&refspecs, Some(&mut opts), None);
11101114
let err = match res {
11111115
Ok(()) => break,
11121116
Err(e) => e,

0 commit comments

Comments
 (0)