Migrating existing patchsets to newer versions of a package

Is there an easy way of applying an existing patchset for an older version of a package to a new version? If I just rename/copy an existing patchset to the latest version, I get this error:

error: sha1 information is lacking or useless

Can I get git to ignore this error and just apply the patches, so that I can create a new patchset with haikuporter -e? Or do I have to apply the patches one-by-one and then amend the authors manually?

That’s mostly how I do it, if there’s an easier way I’m all ears :slight_smile:

1 Like

Off the top of my head, the only way I could think to do it is a script. As HaikuPorts is in Python, I guess that would be the appropriate language.

The script would take a patchfile and step through each patch, prompting at every stage in case one fails. Every time it finishes the last patch in a commit, it runs git add . and git commit. It could then to a final pass to make sure that no information (author, date) was missing or incorrect.

Way off for my skills :slight_smile:

I’m tempted to give it a go. Can’t hurt, right?

3 Likes

Not at my Haiku dev box now, so I’m not sure I’m dealing with all the haikuporter magic.

It seems this happens when the patch can’t be applied directly due to the file having changed. A 3-way merge is tried then, but to do that git needs the file as it was when the patch was generated, the index header line in the patch has the hash to get it, but, as we create a brand new repository without history from the unpacked tarball (or whatever), that blob doesn’t exist and thus the error.

One way to make it work would be to just commit the old contents in a new branch. So, in the unpacked directory:

git checkout --orphan haikuport_old
git reset --hard
<extract content of old version here>
git add -f .
git commit -m 'import old version' -q
git checkout haikuport

You can now check that the blob is there:
git cat-file blob <hash>

I tried this with the gcc2 patchset for iperf 3.13->3.14 and… it didn’t work. In this case there are two patchsets and that is the second one, so I had to also apply the first one to the haikuport_old branch, but you get the idea. After that it was just merge conflict resolutions.

Given that we don’t always regenerate the patchsets when they apply cleanly, I guess it may be possible that this still doesn’t work. In that case apply all the patchsets to the old version and extract them again before going on with the new one.

2 Likes

I have not found a convincing and simple way to do this with git. Usually I have to apply patches by hand or using plain old patch, but I would love to learn of a better solution.

In fact, if you are working on updating to a new version, you probably already have the old one, patched and all, so all you may need is to add that as a remote and fetch it:
git remote add -f prev ../../../work-something/sources/whatever/

Yes, but with the way haikuports working repositories are made, usually you still won’t get a common ancestor for the old and new histories? So, why does this work better than applying the patch directly?

If applying the patch directly works, none of this is needed (or I’m misunderstanding something).

For the 3-way merge to work you don’t really need any history, just the old content.
Say you port v1 of a new project. haikuporter extracts the release tarball and creates a git repo without any history. file1 has some content that git stores as blob upstream1. You need to patch that for Haiku, then compile it, test it and publish it. The patchset will include those changes and have a line (or several if you have more than one commit affecting that file) with something like index upstream1..patched mode. upstream1 and patched are hashes for content, not commits. You can see that content with git cat-file blob <whatever>.

Now you start to port v2. You try using the same patchset but file1 has changed between versions in a way that you get the error about the useless sha1. That’s because to do the 3-way merge git looked for the upstream1 blob and you don’t have it in the v2 working repo. By adding the v1 local repo as a remote and fetching, you do get that blob and now have all you need to try the 3-way merge for file1. In fact, instead of fetching from v1 you may just copy the required blobs from the .git directory if they are not packed, but here be dragons.

The thing is we are not merging branches and keeping a history of commits, but only applying patches to some content. We just need the context of those patches so that they can be applied. Or, well, tried. It may still fail due to conflicts.