What to do when a patch for Mercurial import fails?
Asked Answered
G

2

12

I exported a bunch of changesets from my local working repo after doing a pull from the server repository. To make sure the patches work, I cloned a fresh repo from the server and I tried to apply the changeset. Unfortunately, the import fails with this:

applying G:\OSS\premake-dev\premake-dev_rev493.patch
unable to find 'src/host/scripts.c' for patching
3 out of 3 hunks FAILED -- saving rejects to file src/host/scripts.c.rej
patching file src/base/api.lua
patching file src/host/scripts.c
patching file src/tools/bcc.lua
file tests/test_bcc.lua already exists
1 out of 1 hunks FAILED -- saving rejects to file tests/test_bcc.lua.rej
patching file tests/premake4.lua
patching file tests/test_bcc.lua
abort: patch failed to apply

[command interrupted]

I know the reason for the failure, it's due to a removed source file that no longer exist in the latest changeset. But I'm not sure how to fix up my patch so that it will apply cleanly with the current server repository.

I'm fairly new to Mercurial so some of the terms used I'm not going to be familiar with. Also note that I don't have write access to the Hg server repository. So in order to get my changeset in, I have to export it as a patch and submit that to the maintainers.

Gretagretal answered 4/1, 2011 at 8:56 Comment(2)
How about updating back to the changeset the patch was built for, applying it, committing it, then merging it with the head?Caro
@Lasse thanks for the suggestion. I'll give that a try and report back. This might be worth posting as an answer so it's easier to upvoteGretagretal
C
14

I must confess to not having used patches a lot, so this might not be the right workflow, but what I would try, if I was in that situation was to apply the patch to the changeset it was originally based on.

In other words, it sounds like you have the following case:

                    +-- you're here
                    |
                    v
1---2---3---4---5---6
     \
      \
       X <-- patch was built to change 2 to X

What I would do, provided I know the changeset the patch was originally based on, would be to update back to that changeset, apply the patch, this would add another head, then merge this into the tip of your repository.

After those actions, the repository should look like this:

                        +-- you're here
                        |
                        v
1---2---3---4---5---6---8
     \                 /
      \               /
       7-------------/
       ^
       |
       +-- this is the changeset you committed after applying the patch

Now, for a different way.

Is using a patch the only way? One common way when using Mercurial is that you set up your own repository, a fork, containing originally a full clone of the central repository, but you have commit access.

Thus you can commit your new changesets into your own clone.

If the central repository have new changesets added after you clone, at some point you pull from it into your clone, and merge.

Then when you're satisfied, you issue a pull request to the maintainers of the central repository, telling them that "Hey, I have some changes for you, you can pull them from my clone here: http://...".

This way, it is really easy for those maintainers to get everything in, since you've done all the hard work for them.

This would mean that you have the two repositories like this:

central: 1--2

clone:   1--2

You add your work:

central: 1--2

clone:   1--2--3

They add some changesets:

central: 1--2--3--4--5--6

clone:   1--2--3

Then you pull:

central: 1--2--3--4--5--6

clone:   1--2--4--5--6--7
             \
              \
               3  <-- this is your changeset

Then you merge:

central: 1--2--3--4--5--6

clone:   1--2--4--5--6--7--8
             \            /
              \          /
               3--------/

If the maintainers now pull from you, they get the exact same history into their repository.

There's also some support for rebasing, which would mean that you didn't have to pull and merge, but the maintainers would issue a "pull with rebase" command, in effect relocating your changeset from its current position into a new position in their repository, this would look like this:

central: 1--2--3--4--5--6---7
                            ^
clone:   1--2--3            |  relocated here
               |            |
               +------------+

This would only work if there are no merge conflicts. The method where you pull and merge is the best for them, since you do all the hard work, they only have to verify that the code is what they want.

For more information on forking, check out Tekpub's video on CodePlex and Mercurial, here: Tekpub: 7 - Mercurial With CodePlex, seek to around 21:15 for the forking part to start.

Note that a "fork" is basically just a clone, the way forking works in CodePlex is that it automates setting up a clone on your own account, and sending the original maintainers the pull request, but if you create your own account on Bitbucket or CodePlex or whatever, publish your clone there, and just send the maintainers an email with your repository URL, that's all there is to it.

Caro answered 4/1, 2011 at 10:2 Comment(3)
thanks for the comprehensive write up. Updating my head to an earlier set before applying the patch got me most of the way. +1 for the video, it was pretty helpful and made some things clearer. I think I'll give that forking method a try over at bitbucket.Gretagretal
"Hey, I have some changes for you, you can pull them from my clone here: http://...". Is the process of getting an URL for my repo difficult? I guess I could upload it to the server the main repo is on.Vulgar
To "pull" from somewhere with an url you need somewhere that your repository is hosted. You can host them locally with hg serve but then you would probably have to deal with local ip addresses, firewalls and ports, etc.Caro
P
5

In my case, my failing hg import was related to line endings. The solution was putting this in my ~/.hgrc file:

[patch]
eol = auto
Preraphaelite answered 10/1, 2016 at 9:28 Comment(1)
This also happened to me when Outlook chose to remove "extra" line endings from my emailed patch. Clicking the restore option worked.Vulgar

© 2022 - 2024 — McMap. All rights reserved.