Development/Tasks/Packaging/Tools/Debian Patch Splitter

From Mandriva Community Wiki

Jump to: navigation, search


Debian patches often come in the form of a big patch against the source, and this isn't always really useful. The script on this page allows you to split it into smaller patches.

Wrapper and classifier script

This script will take 2 arguments, a Debian patch and a folder to store the results. The folder will contain 2 other folders, one named addition for new files created by the patch, and one called patch, which will store each patch, named file.diff, for each changed file.

#!/bin/bash
#
# script nom_paquet [ repertoire_destination ]

# TODO support of not compressed file
#      wget on debian archives
#      rewrite of this part in one script
#      more error detection

if [ $# -ne 2 ]; then

        echo "usage: " `basename $0` " packet.diff.gz folder/"
        echo "packet.diff.gz is the patch proved on the ftp mirror"
        echo "folder is the folder where the splitted patch will be found"
        exit 1
fi
DIFF=$1
DOSSIER=$2

mkdir -p $DOSSIER
zcat $DIFF | ( cd $DOSSIER; split_debian.pl )

for i in `find $DOSSIER -type f -maxdepth 1 -name '*.diff' `; do
        FILE=`head -n 1 $i | sed 's/--- //' | sed 's#[^/]*/##'`

        if cat $i | sed '1,3d' | grep -v -q '^[+\\]' ; then
                PREFIX="$DOSSIER/patch"
        else
                PREFIX="$DOSSIER/addition"
        fi

        mkdir -p $PREFIX/`dirname $FILE`
        mv $i  $PREFIX/$FILE
done

for i in `find $DOSSIER/addition -type f`; do
        sed -i 's/^[^+].*//' $i
        sed -i 's/^\+//' $i
done

for i in `find $DOSSIER/patch -type f`; do
        mv $i $i.diff
done

Patch splitting

This scripts split the patch in small chunks, named 1.diff, 2.diff,... It is called split_debian.pl.

#!/usr/bin/perl

$i=0;
$ligne = <STDIN>;

while(1)
{
        # if it begin by '+++ ' or '--- '
        open(FICH ,"> $i.diff")|| die "cannot open file $i.diff";
        $i=$i+1;
        print FICH $ligne;
        # for the +++ line
        $ligne = <STDIN>;
        print FICH $ligne;
        
        $ligne = <STDIN>;
        while ( $ligne =~ m/^@@ / )
        {
                print FICH $ligne;
                @field = split(/ /,$ligne);
                $plus = $field[2];
                $moins = $field[1];
                
                ($p = $plus ) =~ s/\+(.*\,)?//;
                ($m = $moins ) =~ s/\-(.*\,)?//;        

                while($p > 0 or $m >0)
                {
                        
                        $m-- unless ($ligne =~ m/^\+/);
                        $p-- unless ($ligne =~ m/^\-/);
                        $ligne = <STDIN>;
                        print FICH $ligne;
                }
                eof(STDIN) and  exit(0);
                $ligne = <STDIN> ;
                #TODO it may be possible to have more than one of these \ ligne
                #
                if ($ligne =~ m/^\\/)
                {
                        print FICH $ligne;
                        $ligne = <STDIN> ;
                }       
        }
}
Personal tools
Looking for a job?