Radish alpha
h
rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5
Radicle Heartwood Protocol & Stack
Radicle
Git
radicle: Keep pinned repos ordered in config
Archived did:key:z6MkwfcG...bzQA opened 10 months ago

A trivial patch suggested by @Johannes in zulip:

Do not return them in a random order in radicle-httpd, so that we can have them in a defined order in radicle-explorer.

did:key:z6MkwfcG...bzQA opened with revision 72b3f0bd on base 78ba263d +1 -1 10 months ago

A trivial patch suggested by @Johannes in zulip:

Do not return them in a random order in radicle-httpd, so that we can have them in a defined order in radicle-explorer.

fintohaps commented on revision 1 10 months ago

Thanks for the contribution! Changing from a HashSet to a Vec doesn’t preserve uniqueness of the repositories, so I think this change would be more involved. I started sketching a better interface for that:

/// Pin a repository at a given position.
///
/// See [`Pinned::pin`].
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct PinAt {
    rid: RepoId,
    index: usize,
}

impl PinAt {
    /// Construct a new `PinAt` given a [`RepoId`] to pin, and the `index` it is
    /// expected to be pinned at.
    pub fn new(rid: RepoId, at: usize) -> Self {
        Self { rid, index: at }
    }
}

impl Pinned {
    /// Create a new set of [`Pinned`] repositories.
    pub fn new() -> Self {
        Self {
            repositories: Vec::new(),
        }
    }

    /// Return all the pinned [`RepoId`]s.
    pub fn repositories(&self) -> impl Iterator<Item = &RepoId> {
        self.repositories.iter()
    }

    /// Return all the pinned [`RepoId`]s, alongside their index.
    pub fn indexed_repositories(&self) -> impl Iterator<Item = PinAt> + use<'_> {
        self.repositories
            .iter()
            .enumerate()
            .map(|(index, rid)| PinAt { rid: *rid, index })
    }

    /// Pin a repository using a given index. Note that if the index is out of
    /// bounds, then the [`RepoId`] is inserted at the end of the list.
    ///
    /// Ensures that the [`RepoId`] is unique.
    pub fn pin_at(&mut self, pin_at: PinAt) {
        if !self.is_pinned(&pin_at.rid) {
            let PinAt { rid, index } = pin_at;
            // SAFETY: the use of `min` ensures that the `index < len` for the call
            // to `insert`.
            self.repositories
                .insert(index.min(self.repositories.len()), rid);
        }
    }

    /// Pin a repository, by inserting it at the end of the set of repositories.
    ///
    /// Ensures that the [`RepoId`] is unique.
    pub fn pin(&mut self, rid: RepoId) {
        if !self.is_pinned(&rid) {
            self.repositories.push(rid);
        }
    }

    /// Unpin a repository.
    pub fn unpin(&mut self, rid: &RepoId) {
        self.repositories.retain(|rid_| rid_ != rid);
    }

    /// Checks if the given [`RepoId`] is in the set of pinned repositories.
    pub fn is_pinned(&self, rid: &RepoId) -> bool {
        self.repositories.contains(rid)
    }
}

However, I’m still figuring out a nice way to ensure that Serialize and Deserialize ensure this uniqueness property.

lorenz commented on revision 1 9 months ago

Superseded by patch f0c87afd0186a2931ae2c67b7ab026ddc931bfbf