History

Assure that --deepen 0 (despite allowed) doesn't actually confuse the server.

Git does everything except an actual attempt to negotiate for fetching a pack in order to apply purge rules for references for instance, and we do the same.

Sebastian Thiel committed 3 years ago

Commit b43ea6b1 parent c502fa84 files · +64 −9Browse files

Unified · Split

4 files
  1. Makefile +1 −0
  2. gix/src/remote/connection/fetch/negotiate.rs +12 −2
  3. gix/src/remote/connection/fetch/receive_pack.rs +2 −1
  4. gix/tests/remote/fetch.rs +49 −6
Makefile+1−0
@@ -170,6 +170,7 @@ unit-tests: ## run all unit tests · 169 unmodified lines
170170 && cargo test --features blocking-network-client \
171171 && cargo test --features regex
172172 cd gitoxide-core && cargo test --lib
173+# cd gix && cargo test --features async-network-client-async-std \ not being run as it's flaky even locally
173174
174175 nextest: ## run tests with `cargo nextest` (all unit-tests, no doc-tests, faster)
175176 cargo nextest run --all
gix/src/remote/connection/fetch/negotiate.rs+12−2
@@ -1,3 +1,4 @@
1+use crate::remote::fetch;
12 use gix_refspec::RefSpec;
23
34 /// The way the negotiation is performed
@@ -27,12 +28,21 @@ pub(crate) fn one_round( · 23 unmodified lines
2728 fetch_tags: crate::remote::fetch::Tags,
2829 arguments: &mut gix_protocol::fetch::Arguments,
2930 _previous_response: Option<&gix_protocol::fetch::Response>,
30− wants_shallow_change: Option<&[RefSpec]>,
31+ wants_shallow_change: Option<(&fetch::Shallow, &[RefSpec])>,
3132 ) -> Result<bool, Error> {
3233 let tag_refspec_to_ignore = fetch_tags
3334 .to_refspec()
3435 .filter(|_| matches!(fetch_tags, crate::remote::fetch::Tags::Included));
35− let non_wildcard_specs_only = wants_shallow_change;
36+ let (shallow, non_wildcard_specs_only) = wants_shallow_change
37+ .map(|(a, b)| (Some(a), Some(b)))
38+ .unwrap_or_default();
39+
40+ if let Some(shallow) = shallow {
41+ if *shallow == fetch::Shallow::Deepen(0) {
42+ return Ok(true);
43+ }
44+ }
45+
3646 match algo {
3747 Algorithm::Naive => {
3848 assert_eq!(round, 1, "Naive always finishes after the first round, it claims.");
gix/src/remote/connection/fetch/receive_pack.rs+2−1
@@ -118,7 +118,8 @@ where · 117 unmodified lines
118118 con.remote.fetch_tags,
119119 &mut arguments,
120120 previous_response.as_ref(),
121− (self.shallow != Shallow::NoChange).then(|| con.remote.refspecs(remote::Direction::Fetch)),
121+ (self.shallow != Shallow::NoChange)
122+ .then(|| (&self.shallow, con.remote.refspecs(remote::Direction::Fetch))),
122123 ) {
123124 Ok(_) if arguments.is_empty() => {
124125 gix_protocol::indicate_end_of_interaction(&mut con.transport).await.ok();
gix/tests/remote/fetch.rs+49−6
@@ -107,17 +107,60 @@ mod blocking_and_async_io { · 106 unmodified lines
107107 Ok(())
108108 }
109109
110+ #[maybe_async::test(
111+ feature = "blocking-network-client",
112+ async(feature = "async-network-client-async-std", async_std::test)
113+ )]
114+ async fn fetch_shallow_deepen_zero_does_not_fail() -> crate::Result {
115+ let (repo, tmp) = try_repo_rw_args("two-origins", ["--depth=2"], Mode::CloneWithShallowSupport)?;
116+ let daemon = spawn_git_daemon_if_async(tmp.path().join("base"))?;
117+ let remote = into_daemon_remote_if_async(
118+ repo.head()?
119+ .into_remote(Fetch)
120+ .expect("present")?
121+ .with_fetch_tags(fetch::Tags::Included),
122+ daemon.as_ref(),
123+ None,
124+ );
125+
126+ let prev_commits = repo.head_id()?.ancestors().all()?.count();
127+
128+ let changes = remote
129+ .connect(Fetch, gix::progress::Discard)
130+ .await?
131+ .prepare_fetch(Default::default())
132+ .await?
133+ .with_shallow(fetch::Shallow::Deepen(0))
134+ .receive(&AtomicBool::default())
135+ .await?;
136+
137+ assert!(
138+ matches!(changes.status, Status::NoPackReceived { .. }),
139+ "we didn't negotiate at all, but ran all other ref updates"
140+ );
141+ assert_eq!(
142+ repo.head_id()?.ancestors().all()?.count(),
143+ prev_commits,
144+ "no more commits are available - we didn't fetch anything and there would be nothing to fetch"
145+ );
146+ Ok(())
147+ }
148+
110149 #[maybe_async::test(
111150 feature = "blocking-network-client",
112151 async(feature = "async-network-client-async-std", async_std::test)
113152 )]
114153 async fn fetch_shallow_deepen_not_possible() -> crate::Result {
115− let (repo, _tmp) = try_repo_rw_args("two-origins", ["--depth=2"], Mode::CloneWithShallowSupport)?;
116− let remote = repo
117− .head()?
118− .into_remote(Fetch)
119− .expect("present")?
120− .with_fetch_tags(fetch::Tags::Included);
154+ let (repo, tmp) = try_repo_rw_args("two-origins", ["--depth=2"], Mode::CloneWithShallowSupport)?;
155+ let daemon = spawn_git_daemon_if_async(tmp.path().join("base"))?;
156+ let remote = into_daemon_remote_if_async(
157+ repo.head()?
158+ .into_remote(Fetch)
159+ .expect("present")?
160+ .with_fetch_tags(fetch::Tags::Included),
161+ daemon.as_ref(),
162+ None,
163+ );
121164
122165 assert_eq!(
123166 repo.shallow_commits()?.expect("shallow clone").as_slice(),