Search code examples
ubuntudiffpatchrpmdeb

Tool that figures out order in which patches should be applied?


Background:

I am trying to get Ubuntu to work under FIPS mode. One of the packages that I need to FIPSify is openssh. According to CentOS openssh *.spec file one of the patches that they apply on top of openssh source code is openssh-6.6-fips.patch. However, debian packaging code does not have that patch at all so I thought to "borrow" it from CentOS and use on Ubuntu.

Problem:

Unfortunately, this openssh-6.6-fips.patch patch does not apply cleanly on top of ubuntu openssh source code due to other patches that CentOS applied before generating it. I have all the patches, but it is not easy to apply them without conflicts, because I don't know patch dependencies.

Is there an tool that would automate this process and as input would take openssh source code from Ubuntu, patches from CentOS and "target" patch that I want to apply. And then in output it will tell me if (and how) it is possible to apply these CentOS patches without triggering conflicts?


Solution

  • The tool to use for this is a version control system, and I will show (completely untested) git commands of how I would do it.

    ## Create repository ##
    $ mkdir workdir
    $ cd workdir
    $ git init
    $ touch .gitignore             # \   Creates a first commit
    $ git add .gitignore           #  >  for the branches to
    $ git commit -m .gitignore     # /   have in common
    
    ## Import debian source code ##
    $ git checkout -b debian master
    $ tar zxvf /the/debian/source/code.tgz
    $ git add .
    $ git commit -m "Base debian source code"
    
    ## Import centos source code ##
    $ git checkout -b centos master
    $ tar zxvf /the/centos/source/code.tgz
    $ git add .
    $ git commit -m "Base centos source code"
    
    ## Apply centos rpm patches ##
    $ pacth -p1 < /the/file/listed/as/patch1/in/spec/file
    $ git add .
    $ git commit -m the_pacth1_file_name
    
    $ pacth -p1 < /the/file/listed/as/patch2/in/spec/file
    $ git add .
    $ git commit -m the_pacth2_file_name
    
    $ # repeat for all the patches up till, including openssh-6.6-fips.patch
    

    So far the command have gotten you nothing other than a git repository that contains the final source code used when building a package. However since the patches are stored as separate commits (this is the key), we can do standard version control manipulation and include/exclude parts of the branches as we want.

    So assuming openssh-6.6-fips.patch is patch number 5 just to pick a number, your problem is that it does not apply cleanly to the ubuntu source because of some additional changes in done in patches 1 to 4 which it builds on top of, right?

    A proper version control system keeps track of parent relations to versions, and with luck it will figure out how to resolve conflicts on its own, or it might give up and you need to resolve it manually, but in any case, a version control system is the best tool there is to handle such situations.

    So if the only patch you want from the centos source code is openssh-6.6-fips.patch, then you create a new branch containing just this patch on top of the base centos source code commit, and then rebase that branch onto the ubuntu branch. That rebased commit will then give you a patch that will apply cleanly onto the ubuntu source code

    $ git checkout -b fips centos
    $ git rebase -i master      # Pick only the first base commit
                                # and the openssh-6.6-fips.patch
    $ # Resolve conflicts if any and check in
    

    Now you have a branch fips which only contains the centos base source code and the fips commit. Then you want to rebase this onto the ubuntu branch.

    # Rebase from (excluding) one behind the top of fips branch,
    # to (including) the tip of the fips branch
    $ git rebase --onto ubuntu fips^ fips
    # Resolve and check in any conflicts should there be any
    $ git format-patch ubuntu..fips
    

    The last command will give you a patch file that will apply cleanly that you can add to the packaging code.