Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modify pins #84

Open
piegamesde opened this issue Jun 14, 2024 · 2 comments
Open

Modify pins #84

piegamesde opened this issue Jun 14, 2024 · 2 comments

Comments

@piegamesde
Copy link
Collaborator

Currently the way to modify pins is to simply re-add them with the new configuration. I think it would be good to have some shortcuts for the most common use cases:

  • Switch a channel
  • Switch from a release to a branch and back
  • Limit the version
  • Maybe: switch to a fork? Generally changing the pin modalities should be easier than changing the target source

My first idea was a generic modify command (similar to Niv), however which CLI flags are be valid would change based on the kind of the pin being modified. But also having a modify-github etc. for each kind of pin is a bit tedious.

So instead, maybe have one modify command per action or class of actions? As long as changing the source itself is not supported, all git-likes can be handled together with the same options. This would leave channels and pypi as separate though.

@andir
Copy link
Owner

andir commented Jun 14, 2024

I've thought about it a few times... So far I've just manually edited the JSON as that seemed the least troublesome to me. niv solves this by having a bit of "typelevel magic" (probably not the wrong Haskell term 😅) to modify arbitrary attributes on a pin (IIRC).

We should also consider only allowing users to change what they can already provide while adding a pin. Allowing a user to change e.g. the hash sum might have a valid use case, but those should be bugs in npins. If you need to mock with "generated" fields, something else is missing. You can always resort to JSON editing if you need that.

So the "source" and version bounds sound like a good candidate for these changes.

If we added some new trait for each kind of Pin that allowed some introspection-like behaviour for fields we can likely solve this without a ton of effort.

My rough idea would be:

pub trait Editable {
    /* const */ fn get_fields(&self) -> Vec<(FieldName, FieldType)>;
    fn modify(&mut self, field: FieldName, value: FieldValue);
}

pub enum FieldType {
    String,
    Integer,
    Url,
    Optional(FieldType),
    // ....
}

pub enum FieldValue {
    String(String),
    Integer(i64),
    Url(url::Url),
    Optional(Option<FieldValue>),
    // ...
}

impl FieldValue { 
    fn type(&self) -> FieldType {
       use Self::*;
       match self {
         String(_) => FieldType::String,
          // ...
       }
    }
}

impl Editable for GitHubRelease {
   /* const */ fn get_fields(&self) -> Vec<(FieldName, FieldType)> {
     vec![("owner".into(), FieldType::String), ("repo".into(), FieldType::String), ("version-bound".into(), FieldType::Optionall(FieldType::String))] 
  }
     fn modify(&mut self, field: FieldName, value: FieldValue) -> Error<()> {
       use FieldType::*;
        match (field, value.type()) {
            ("owner", String(s)) => self.owner = s.into(),
            ("owner", _) => return Err("invalid value for field `owner`".into()),
        }
     }
}

We can likely auto-generate most of the code if we add a list of editable fields to our already load-bearing macro.

@piegamesde
Copy link
Collaborator Author

I'm honestly not a big fan of Niv's approach of letting you modify individual fields. Because often times, fields depend on each other and have invariants. But also they already depend on the pin type and stuff. Abstracting over that means that the CLI cannot guide the user as to which fields can be meaningfully changed in which way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants