-
Notifications
You must be signed in to change notification settings - Fork 12
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
Update Feature #44
Comments
CC-ing also @satraul. If you plan to update just the two fields, there's also his new |
So after thinking about how the interface between upt and backend will be like and what will go where following is what I have come up with: Frontend parses upt -> So in psuedo code something like:
Backend will have to implement : and also this whole function can be overridden by backends in case they want to do something different, for example as mojca suggested for MacPorts we can use What do you think about this? |
I think the general outline looks fine; at least from my perspective, but I'll defer to @Steap for everything touching Ideally, I would prefer to skip all the intermediate "extract_update" stuff and just do
but again, I don't know how feasible that is. I'll need to play around with some of the tools like |
Hello,
On 2019-07-11 19:33, Karan Sheth wrote:
So after thinking about how the interface between upt and backend will be like and what will go where following is what I have come up with:
Frontend parses upt ->
Backend reads the existing file ->
Backend extracts information to be updated (example for macports for now it can be version line and checksums line)....When I say extract means not the value but just the lines itself as we don't need the exact info as demonstrated above ->
Backend generates update file using a update template ->
So basically these are the small files that only contain (for now)
"versions" and "checksums", right?
upt generates patch file using both of this ->
upt passes patch file, diff file, new file to backend ->
Backend saves required files.
This honestly seems overly complicated. We need to extract data from an
existing Portfile, do some work "on the side", re-inject everything into
the backend and have it handle a merge.
It seems difficult to implement (for MacPorts, let alone other
backends) and error-prone.
Or maybe I'm misunderstanding something?
|
What can port bump do, exactly?
So, my initial idea for update was to parse CPAN/PyPI/Rubygems/etc. for 2 different versions and generate a high-level diff ("these are the new requirements", "these requirements are no longer needed", etc.). At first, it seemed doable for PyPI: https://pypi.org/pypi/requests/0.10.0/json <- an old version It seemed doable for CPAN as well: https://fastapi.metacpan.org/v1/release/NEILB/AppConfig-1.70 <- an old version But I do not think Rubygems (and other frontends to be added in the future) will provide info about all versions of a package. Also, it should be noted that some info is missing from these REST API. For instance, the test requirements for "requests" do not show up on PyPI (for various reasons that I won't go into here). Wouldn't the best way to update just be to create a "Portfile.new" file, and then have the user run diff/git diff/whatever? |
I wrote this and forgot to hit send before I read your replies: I just want to reiterate: updating just port version and checksums is something that already What I would really like to see is at least some rudimentary support to tell you which dependencies changed between the two versions. I don't mind as much if I need to add those manually for a moment, but figuring out the exact dependencies is really the most time-consuming step which I very strictly :) always ignore when I need to do some mass update. We should be able to extract both old and new dependencies from the two versions, compare them, and at least tell the user:
|
The v2 of rubygems api seems to support this: But yeah you are right maybe all frontends doesn't support this. I agree that the whole process is a bit complicated so maybe we can divide that into two parts and do the following:
Now optionally backends can implement apply_update feature which is backend specific:
Is this fine? |
I agree that Cyril initial idea to "generate a high-level diff" would be a good one, but indeed probably not doable for all frontends. Generating a new Portfile can and should be done for sure, in addition to making a diff between the two files; no problem there. I also like Karan's idea of implementing an optional "apply_update" function (or whatever name) in the backend to do something more specific. I am not a fan of doing Again, I don't like making separate intermediate diff files to patch the Portfile. This should be something people have done before and I would suggest you to investigate things like @Steap can we first agree on how/what should be implemented in |
So, here is an updated (pun indented) idea of how to do things:
class PackageDiff(object):
def __init__(self, old_pkg:upt.Package, new_pkg:upt.Package):
self.version = new_pkg.version
def new_requirements(self):
pass
def deleted_requirements(self):
pass upt.PackageDiff.new_requirements would be similar to upt.Package.requirements, but would only return the new requirements. TODO: figure out what else we might want to access from a PackageDiff.
class MacPortsBackend(upt.Backend):
def update_package(self, pkgdiff:upt.PackageDiff):
... Now, it's up to the backend to do the right thing. Can the backend easily make the required modifications? If not, maybe the abstraction I've proposed is not really good. |
Sounds great, I have a few doubts(not even sure they are doubts)...so I will first code this up and if anything goes wrong then I will ask. |
Ok so all of what @Steap suggested is done more or less...now before coming to upt-macports. For upt-macports backend, this are the things I think we will do:
Anything else that you think we should be doing? |
@Steap I fully agree with your latest proposal! I don't understand though how this differs from you first "high-level diff" that seemed not supported by all the frontends. Anyway, if you think this will work I think it's a great way of doing this, so let's go for it! @Korusuke as I said earlier I would prefer not to do Of course, we could decide to finalize the pieces needed for |
Ok my bad, I somehow tested diff match patch wrongly or missed out..... but testing again with all the output that current idea is giving, it works unbelievably amazingly well :) |
@reneeotten Yes, this is the same "high-level diff" approach. If some frontends do not give us access to all versions of a package, well, too bad. We could always ask the backend to parse their own files if needed, by the way. Maybe we could improve "port bump" instead of implementing everything in upt-macports? I'm not sure exactly how "port bump" works, though. |
Perhaps, but it's written in Tcl, which is pretty much voodoo to me ;) Looking at the man-page it will only update the checksums and reset the revision, after updating the version number of a port by the maintainer. If we first need to update the version number and then run |
Hi all. I haven't been following the discussion closely, but it is already planned for me to implement a Is this the use case needed? I can prioritize working on this feature if so. |
We have the GSOC student who implement this as a challenge task during proposal submissions (@satraul) and could improve the tool if needed.
True.
True. What Maybe my message was misunderstood before / I was not clear. What
@satraul: yes, updating version would be nice, or support something like What would also be cool as the "last step" for both tools ( |
Agreed that it's useful for other ports, but as I've been trying to say for a while now it should not be used here. We have the same information (and much more) easily available from We can then figure out which part of the code should go (as default option for example) into I would like to see, at least in the testing phase, the following:
|
Version for Edit: Nope I was wrong, it's weird as in Portfile the version is right but App-rad: version is 1.05 So I guess we should fix port info first as this is important for both update as well as recursive feature to work. What do you think ? |
Edited a bunch of stuff in previous comment and as the github mail won't contain that so ping :) @reneeotten @mojca @Steap |
Version numbers in perl are... interesting. The observation above is only true for upstream modules that use a decimal number for their version. Our version comparison doesn't support such numbers, e.g. 1.10 is considered bigger than 1.2. The perl5.setup proc transforms the version in a way that should match what is done by Further reading: https://metacpan.org/pod/version |
thanks for the explanation @jmroot In that case we should do the same transformation of the upstream version in |
The check about version checking actually takes place in upt-core and not in upt-macports which is only responsible of returning the current version. For doing this although I was highly skeptic about it working, I replicated the existing proc in python and then tried to invert it which "kind of wokrs" but not always. -Upstream version: 1.2.3 So basically if the original upstream version has two decimal points then we don't have to apply any transformation. I am kinda stuck and don't think there's any way to correct this script.
|
@Korusuke I looked a bit more today and I tend to agree with you that reverse engineering the upstream package version is difficult to do correctly. For example, all these "Portfile" versions [1.1, 1.10, 1.100] would give the same "Perl converted" version (v1.100.0) so it's pretty much impossible to get back to the upstream version from Ideally, I prefer not overwrite the It seems to me that the recommended way of comparing Perl package versions is to first convert them as described in the link that @jmroot gave above. If that's the case, what about putting that logic in |
I am horrified. I really wonder how Perl ended up with something this complicated just to specify a version. I do not really understand why needs_requirement would have anything to do with this. Can you tell me more about what you had in mind? |
Sure, there might be other/better ways and it's possible that I'm far off here, but.... my thought process this afternoon and how For example, upstream has its version set to “1.04” so this is what Now, let’s assume this package in MacPorts becomes outdated and version “1.05” is released and we attempt to package another package that requires this version. Currently, in However, it seems to me that similar issues can appear as well if requirements and upstream versions are expressed differently. From the link mentioned above: “If you need to compare version numbers, but can't be sure whether they are expressed as numbers, strings, v-strings or version objects, then you should use version.pm to parse them all into objects for comparison.” So what I am proposing is to add a Python function to In other words, in pseudo-code something along those lines:
in the
and a little further down:
Apologies for the very long post.... but it seems to me this solves the issue for MacPorts and at the same time will work in a backwards-compatible way for all backends. As an additional bonus it should help for all backends when version are expressed differently (as described above). Let me know what you think and I am certainly open for other, simpler solutions ;) |
So this is also an issue for recursive packaging, right? Rather than having a bunch of if/else in needs_requirement, one solution would be to "fix" upt-cpan, and always use "normalized" versions. I'm not sure exactly what other backends expect, so I'm a bit reluctant to make this change right now. A workaround for macports would be to override need_requirement in this way: def need_requirement(self, req, phase):
new_req = ... # modify the requirement to have a "standardized" version" if needed
super().need_requirement(new_req, phase) This way you only implement the "magic" conversion (which may or may not be moved to upt-cpan later) and still take advantage of the regular need_requirement version. What do you think? |
@Steap long-term it might be indeed worthwhile to move to the normalized/standardized version in Your suggestions is a very good one, I should have thought about using @Korusuke does the discussion above and the suggested solution makes sense to you - if so, can you give this a try. I think we should implement this in a separate PR; if we can resolve this for the already merged "recursive packaging feature", it should also work for the "update feature". |
So after trying a bunch of things like diff-match-patch, normal diff and vaguely trying regex following is the technique that works best at least for situations that I tried.
Let's say we have a Portfile which we need to update and we have decided that we will update
version
andchecksums
field.So first we extract that fields from existing Portfile (yet to be automated).
and make a file which looks like this:
and then we generate a new file which looks like this:
Notice the blank line at end of file, that is apparently important for this to work.
Now we generate a diff for above two files and then apply patch on the original file.
This even updates a file that maybe modified and has different order of fields than what upt usually has.
For example from this:
to this:
The text was updated successfully, but these errors were encountered: