-
Notifications
You must be signed in to change notification settings - Fork 8
Added support for inheritance in importing repository files. #39
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
base: main
Are you sure you want to change the base?
Conversation
898c082
to
3361a90
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some comments and suggestions.
More of a long-term, high-level discussion: Did you see the discussion on the original PR about being able to extend multiple files and import multiple files and the semantics of that? dirk-thomas/vcstool#148 (comment). How do you think that should behave? Dirk was suggesting not allowing (warning or erroring on) identical entries for sibling files: not allowing two files being extended to contain the same repository path (e.g., src/vcs2l:
under repositories:
). I think I kind of missed that back then and intended to just merge sibling entries and prioritize from top to bottom instead:
extends:
- a.repos # May override entries from b.repos
- b.repos
repositories:
repo: ... # May override entries from the combination of a.repos and b.repos
We can probably figure this out after this PR, though.
Signed-off-by: Leander Stephen D'Souza <[email protected]>
Signed-off-by: Leander Stephen D'Souza <[email protected]>
Signed-off-by: Leander Stephen D'Souza <[email protected]>
3361a90
to
8c7697c
Compare
Yes, it was quite straightforward to extend the implementation to support multiple files. I have included documentation, tests and error support if the user tries to include duplicate files. |
I can understand that the documentation can take up a lot of space in the README. |
Sorry, I meant to initiate a discussion and not really request you to implement something, because, from the initial discussion with Dirk, there were two options when supporting multiple files under
I think Dirk's point was that it makes sense for a file extending another file to override some paths (repos), but it may or may not make sense for a file being extended to override some paths from another file being extended alongside it. |
Signed-off-by: Leander Stephen D'Souza <[email protected]>
Signed-off-by: Leander Stephen D'Souza <[email protected]>
Apologies for misreading the conversation. I can drop the specific commit if this does not pertain to the PR.
I am currently not allowing the user to specify the same path by raising the error here. I feel that this is a more simplistic approach, which limits the user to specifying distinct paths as part of the extended files. Please let me know if this is a viable method to follow through, as this file structure can be restrictive and opinionated. |
Sorry, my comment wasn't clear, especially without the original context. See my updated comments. By "the same paths," I meant the same repository paths (not In any case, I think allowing identical repository paths/entries is fine for now. I can see having a |
…e in import command. Signed-off-by: Leander Stephen D'Souza <[email protected]>
Oh my bad, I think since we are allowing duplicate repository entries as of now, this should be resolved.
Yes, sure. I can add this as a feature request issue once this PR gets merged with |
try: | ||
# Recursively get repositories from parent file | ||
with open(parent_file, 'r', encoding='utf-8') as parent_f: | ||
parent_repos = get_repositories(parent_f, visited_files.copy()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In a quick look, this .copy()
operation caught my attention here. Is it really required? Can we find a bug that happens in no copy is performed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this is required.
This is to ensure that each DFS iteration gets its own copy of visited_files
to work with.
This is to prevent unnecessary CircularImportError
exceptions from being raised when the extended files have the same dependency.
For instance, consider the following example:
base.yaml
extends: [a.yaml, b.yaml]
a.yaml
extends: shared.yaml
b.yaml
extends: shared.yaml
shared.yaml
(no extends)
Without .copy()
:
- Process
base.yaml
→ adds it tovisited_files
- Process
a.yaml
→ adds it to the samevisited_files
set - Process
shared.yaml
→ adds it to the samevisited_files
set - Return from processing
a.yaml
- Try to process
b.yaml
→ adds it tovisited_files
- Try to process
shared.yaml
again -CircularImportError
due to step 3.
TLDR: The .copy()
method prevents sibling files with the same dependency from raising a circular import error.
Thanks @leander-dsouza for implementing this, quite a nice work of defining the semantics and the implementation. I just left a minor command, overall looks great. As a proof of concept I used this and encode gazebodistro files for the Jetty distribution gazebo-tooling/gazebodistro#224 and 🎉 almost everything removed but the codification of the library sources and a declaration of their dependencies in each file. Isn't wonderful? Couple more of comments: for packaging in debian (particularly for the testing) we are going to need "offline" tests, but I saw that @cottsay was already coded a solution. I'm not particularly fan of encoding the shell output for testing, but i think that this is how the repository tests were implemented so it is more a topic for a repository wise discussion. |
I'm also not thrilled about the console output captures. I think we all have a handful of changes we want to make to the testing for this package. Trying to keep #72 focused on getting things offline first, then we can make incremental improvements. |
I see the point of this change, but solution is not great imo:
Accepting multiple repo lists and merging them sequentially seems to be less invasive and more flexible. |
Thank you for the feedback, Alex.
The implementation in this PR is a sequential merge of multiple YAML files with priority. If you take how the repository files are defined in gazebo-tooling/gazebodistro#224, having multiple inheritance is a great way to simplify files. Moreover, you can have a single base template of dependencies and create "children" for your cause by merely overriding a particular dependency choice.
The addition of the
The paths to the |
|
Apologies for implying the changes are EEE. This was motivated by a feature request mentioned at dirk-thomas/vcstool#148. Since the tool is regularly used in the community, I appreciate your concern. Could you please provide some examples/scenarios that this incoming change would prove to be inferior to your implementation at
The tool currently can be extended from multiple bases/repository files. There are no restrictions on the amount of extensions you can have for your implementation. |
I am sorry I wasnt clear:
but what if you need
The issue here is that extended files are hardcoded. |
Multiple inheritance is supported in this contribution. For your above use case, the syntax is as follows (example file): ---
extends:
- base_1.yaml # Lower priority
- base_2.yaml # Higher priority
repositories:
vcs2l:
type: git
url: https://github.com/ros-infrastructure/vcs2l.git
version: 1.1.5 Could you please clarify what do you mean by:
You can refer to some of the tests attached for each possible use case as well. |
Either base1 or base2, e.g., two versions of a package stack maintained by different teams or targeting different platforms are extended by the same patch provided by a third party.
It is not about relative or absolute paths: consider a situation where repolists are located in separate repos that are checked out in arbitrary locations. Assumption that both the base and extending repo lists are distributed together is too strong. |
@asherikov thanks for explaining a bit further, I'm trying to understand the use cases / potential drawbacks you are presenting here:
The current implementation supports extending from multiple bases like you comment and merges yaml files by taking the latest appearance of a specific repo. The updated README has a detailed write up on how this is structured. Could you exemplify why this wouldn't work for your use case ?
This is a limitation of the current implementation as I understand it (correct me if I'm wrong @leander-dsouza). You cannot input an extension repolist that is not distributed in the same repo you are defining the extension, there is a locality concept to the implementation. I see the value of being able to extend from external sources when compositing your repolist, though I'm not certain where the balance falls between the added complexity and value.
This was discussed in the OG issue and what I think is lost by just allowing multiple repolists on |
Nope, this is a different use case. I dont mean to extend two bases simultaneously, but rather to extend either one or another, with the current implementation you would have to either maintain two versions of extension file, or edit
Ordering quite naturally implies priority, same as in your example:
If necessary an extra parameter may specify how conflicts are to be handled, e.g., fail, prioritize last/prioritize first. |
Basic Info
Description of contribution in a few bullet points
extends
field forvcs import
to facilitate inheritance.extends
feature.Description of how this change was tested
Ran
pytest
locally to ensure all the unit and linting tests pass:pytest -s -v test
Created a local fork to validate green CI.
Signed-off-by: Leander Stephen Desouza [email protected]