Skip to content

Commit

Permalink
Make it possible to ignore specs that don't match when iterating mapp…
Browse files Browse the repository at this point in the history
…ings. (#450)

This is an issue if `HEAD` as refspec is added after all other specs,
but isn't serialized. Then at a later stage, the remote is restored from
disk but won't contain one of the refspecs that was used for the
mapping.
  • Loading branch information
Byron committed Oct 17, 2022
1 parent 700cc2d commit bc991ff
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 12 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ Please see _'Development Status'_ for a listing of all crates and their capabili
* [x] **ref-map** - show how remote references relate to their local tracking branches as mapped by refspecs.
* [x] **fetch** - fetch the current remote or the given one, optionally just as dry-run.
* **clone**
* [ ] initialize a new **bare** repository and fetch all objects.
* [ ] initialize a new repository, fetch all objects and checkout the main worktree.
* [x] initialize a new **bare** repository and fetch all objects.
* [x] initialize a new repository, fetch all objects and checkout the main worktree.
* **credential**
* [x] **fill/approve/reject** - The same as `git credential`, but implemented in Rust, calling helpers only when from trusted configuration.
* **free** - no git repository necessary
Expand Down
17 changes: 9 additions & 8 deletions git-repository/src/remote/connection/fetch/update_refs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,13 @@ pub(crate) fn update(
let mut edits = Vec::new();
let mut updates = Vec::new();

for fetch::Mapping {
remote,
local,
spec_index,
} in mappings
{
for (remote, local, spec) in mappings.iter().filter_map(
|fetch::Mapping {
remote,
local,
spec_index,
}| refspecs.get(*spec_index).map(|spec| (remote, local, spec)),
) {
let remote_id = remote.as_id();
if dry_run == fetch::DryRun::No && !repo.objects.contains(remote_id) {
updates.push(update::Mode::RejectedSourceObjectNotFound { id: remote_id.into() }.into());
Expand Down Expand Up @@ -83,14 +84,14 @@ pub(crate) fn update(
let (mode, reflog_message) = if local_id == remote_id {
(update::Mode::NoChangeNeeded, "no update will be performed")
} else if let Some(git_ref::Category::Tag) = existing.name().category() {
if refspecs[*spec_index].allow_non_fast_forward() {
if spec.allow_non_fast_forward() {
(update::Mode::Forced, "updating tag")
} else {
updates.push(update::Mode::RejectedTagUpdate.into());
continue;
}
} else {
let mut force = refspecs[*spec_index].allow_non_fast_forward();
let mut force = spec.allow_non_fast_forward();
let is_fast_forward = match dry_run {
fetch::DryRun::No => {
let ancestors = repo
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ impl std::fmt::Display for Mode {
impl Outcome {
/// Produce an iterator over all information used to produce the this outcome, ref-update by ref-update, using the `mappings`
/// used when producing the ref update.
///
/// Note that mappings that don't have a corresponding entry in `refspecs` these will be `None` even though that should never be the case.
/// This can happen if the `refspecs` passed in aren't the respecs used to create the `mapping`, and it's up to the caller to sort it out.
pub fn iter_mapping_updates<'a, 'b>(
&self,
mappings: &'a [fetch::Mapping],
Expand All @@ -102,15 +105,15 @@ impl Outcome {
Item = (
&super::Update,
&'a fetch::Mapping,
&'b git_refspec::RefSpec,
Option<&'b git_refspec::RefSpec>,
Option<&git_ref::transaction::RefEdit>,
),
> {
self.updates.iter().zip(mappings.iter()).map(move |(update, mapping)| {
(
update,
mapping,
&refspecs[mapping.spec_index],
refspecs.get(mapping.spec_index),
update.edit_index.and_then(|idx| self.edits.get(idx)),
)
})
Expand Down
1 change: 1 addition & 0 deletions gitoxide-core/src/repository/fetch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ pub(crate) mod function {
let mut last_spec_index = usize::MAX;
let mut updates = update_refs
.iter_mapping_updates(&map.mappings, refspecs)
.filter_map(|(update, mapping, spec, edit)| spec.map(|spec| (update, mapping, spec, edit)))
.collect::<Vec<_>>();
updates.sort_by_key(|t| t.2);
for (update, mapping, spec, edit) in updates {
Expand Down

0 comments on commit bc991ff

Please sign in to comment.