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

Config access uses impl Key to allow type-safe keys #1236

Closed
wants to merge 11 commits into from

Conversation

bittrance
Copy link
Contributor

@bittrance bittrance commented Jan 5, 2024

This PR changes the API of gix_config::File to use a trait (gix_config::Key) as key when requesting or setting configuration. This will allow gix to use its tree of structured and validating typed keys (gix::config::tree::sections::*) as keys directly, and also means that consumers of the gix crate to use type-safe config access. gix-config also provides an implementation for &str and &bstr so that constant strings can be used as keys. This is part of the work addressing #1125.

The PR is draft, as there remains various question marks, see specific comments in code below.

gix contains a lot of strings and format!() operations that could be changed to use type-safe keys, but that is left for a separate PR.

Tasks

  • initial refactor
  • get repository tests to work and remove TODOs around mutations (see as_config_key())
  • call key parameters value_name instead to be in sync with KeyRef::value_name, also see keys() methods
  • proper split into commits with breaking-change signalling and documentation of breaking changes

@bittrance bittrance changed the title Config access uses impl Key to allow structured keys Config access uses impl Key to allow type-safe keys Jan 5, 2024
gix-config/src/traits.rs Outdated Show resolved Hide resolved
Copy link
Member

@Byron Byron left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for sharing your amazing progress!

Before I can look at anything in detail, I'd need the commits split up so that…

  • …the Key related changes in gix-config are in one commit, whose subject is prefixed with fix!: or feat!: . Please write the subject and body so they can go into the changelog.
  • …all other changes to adapt to this change can go into its own commit without any special message requirements.

There is also this one big request of only modifying the string_by_key based access with the new trait. After all, the natural way of accessing the API is by passing triplets of section, subsection and 'key' (definitely open to a better term here).

That way, only string_by_key() has to change at all and that change would probably be compatible to most existing uses depending on the available implementations of Key for &BStr for example. I don't think there is a need to break the world here, and hope this could even work without making any breaking change.

Is that feasible at all?

@bittrance
Copy link
Contributor Author

…the Key related changes in gix-config are in one commit, whose subject is prefixed with fix!: or feat!: . Please write the subject and body so they can go into the changelog.

Is the purpose simply to have a feat! commit in the history? If so, I'd just split out adding the Key trait into a separate commit, no problem. The current commit looks like it does because I'm always striving for every commit to be viable (i.e. buildable and git-bisect:able) and still be meaningful.

There is also this one big request of only modifying the string_by_key based access with the new trait. After all, the natural way of accessing the API is by passing triplets of section, subsection and 'key' (definitely open to a better term here). That way, only string_by_key() has to change at all and that change would probably be compatible to most existing uses depending on the available implementations of Key for &BStr for example. I don't think there is a need to break the world here, and hope this could even work without making any breaking change.

I was thinking we should keep the API surface small by removing all the _by_key method so that only the impl Key versions remained (I prepared bittrance@c54bb3a for this purpose). My thought is that gix config API should encourage using type-safe access and I think config.string(format!("foo.{submod}.bar")) is more readable than config.string("foo", submod, "bar"), but I defer to your judgement on when it is worth making a breaking API change.

@Byron
Copy link
Member

Byron commented Jan 5, 2024

Is the purpose simply to have a feat! commit in the history? If so, I'd just split out adding the Key trait into a separate commit, no problem. The current commit looks like it does because I'm always striving for every commit to be viable (i.e. buildable and git-bisect:able) and still be meaningful.

No, the purpose is to have a changelog that applies to the gix-config crate exclusively - otherwise cargo smart-release would think there are breaking changes in all of the crates whose code was adjusted, and it will claim new features in their changelogs, too.

That takes priority over each commit being green on CI, it's all trade-offs.

I was thinking we should keep the API surface small by removing all the _by_key method so that only the impl Key versions remained (I prepared bittrance@c54bb3a for this purpose). My thought is that gix config API should encourage using type-safe access and I think config.string(format!("foo.{submod}.bar")) is more readable than config.string("foo", submod, "bar"), but I defer to your judgement on when it is worth making a breaking API change.

Thanks for sharing your thoughts.

For a plumbing crate, it would already be more than fine. However, it's exposed in gix and thus it needs to provide more support for a nicer API, but that shouldn't supersede the 'API that is natural for the data', i.e. triplets as it's without overhead.

But since you would be touching all of these methods anyway, let's encourage the use of the potentially typesafe and nicer API by making their methods the shorter ones. This means, for example, to keep File::string(key: impl Key) as is, but have a longer method that takes the triplet, like File::string_by(section, subsection, key). The _by suffix is an example but something that seems to work nicely, and it seems better than my initial thought _by_triplet() which is punishingly long.
Please do feel free to experiment (and bikeshed) with the suffix though.
Finally, this also means that string() would call string_by().

I hope all that makes sense, please do let me know about any concern you might have as well.

@bittrance bittrance force-pushed the config-key-take-2 branch 2 times, most recently from f1d7e94 to 00f7c28 Compare January 30, 2024 18:35
gix-config/src/file/access/comfort.rs Outdated Show resolved Hide resolved
gix-config/src/file/access/comfort.rs Outdated Show resolved Hide resolved
gix-config/src/file/access/comfort.rs Outdated Show resolved Hide resolved
Copy link
Member

@Byron Byron left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks so much for the changes!

It's wonderful to see how the standard-API of gix-config can be enhanced by the Key trait. While looking at it more closely, I also noticed something else that I think can be fixed without too much overhead.

But if that work should ever appear overwhelming or boring because the API surface is quite massive, please let me know and I can help doing the refactoring. The last thing I'd want is for you to get exhausted due to all these comments of mine 😅.

Just let me know how I can help and I will try to make it happen.
Thanks again!

gix-config/src/impls.rs Outdated Show resolved Hide resolved
gix-config/src/tests.rs Outdated Show resolved Hide resolved
@Byron
Copy link
Member

Byron commented Apr 22, 2024

As a note, I plan to finish this PR myself once I get a chance.

Conflicts
---------
	gix-config/src/file/init/from_env.rs
	gix-config/src/parse/mod.rs
	gix/src/config/cache/access.rs
	gix/src/config/cache/incubate.rs
	gix/src/config/overrides.rs
	gix/src/repository/index.rs
@Byron Byron force-pushed the config-key-take-2 branch 5 times, most recently from 006e661 to 45d9709 Compare June 21, 2024 17:36
- reorganize `Key` trait implementation
- make it possible to use it as reference (and thus re-use the impl when passing it
  to another function that takes a `Key`
- make it less wasteful to obtain the parts of a Key
- where possible, rename methods to `*_by`, while the original method is replaced
  by one that uses a  `key: impl AsKey` instead. That way, the methods that
  are easiest to call are the shortest ones, while still providing the ones
  that take tuples like before.
@Byron
Copy link
Member

Byron commented Jun 21, 2024

The content of this PR was merged to main, but I forgot to push before changing the commit message, hence GitHub doesn't see the merge happened.

Thanks again for getting this started!

@Byron Byron closed this Jun 21, 2024
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

Successfully merging this pull request may close these issues.

3 participants