mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-04-13 14:42:51 -07:00
Rewrite of patch system to simplify mainting large patchsets.
This commit is contained in:
commit
ef427399da
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*.ok
|
||||
.depcache
|
93
README.md
93
README.md
@ -1,23 +1,84 @@
|
||||
wine-compholio
|
||||
==============
|
||||
|
||||
The Wine "Compholio" Edition repository includes a variety of patches for Wine to run common Windows applications under Linux.
|
||||
The Wine "Compholio" Edition repository includes a variety of patches for
|
||||
Wine to run common Windows applications under Linux.
|
||||
|
||||
Current patches include:
|
||||
These patches fix the following Wine bugs:
|
||||
|
||||
* Support for TransmitFile ([Wine Bug #5048](http://bugs.winehq.org/show_bug.cgi?id=5048 "Multiple applications and games need support for ws2_32 SIO_GET_EXTENSION_FUNCTION_POINTER TransmitFile (WSAID_TRANSMITFILE)"))
|
||||
* Support for Junction Points ([Wine Bug #12401](http://bugs.winehq.org/show_bug.cgi?id=12401 "Support junction points, i.e. DeviceIoCtl(FSCTL_SET_REPARSE_POINT/FSCTL_GET_REPARSE_POINT)"))
|
||||
* GetSecurityInfo returns NULL DACL for process object ([Wine Bug #15980](http://bugs.winehq.org/show_bug.cgi?id=15980 "Rhapsody 2 crashes on startup (GetSecurityInfo returns NULL DACL for process object)"))
|
||||
* Workaround for TransactNamedPipe not being supported ([Wine Bug #17273](http://bugs.winehq.org/show_bug.cgi?id=17273 "Many apps and games need SetNamedPipeHandleState implementation (support for named pipe message mode)(FireFox+Flash, Win8/NET 4.x SDK/vcrun2012, WiX installers)"))
|
||||
* Support for process ACLs ([Wine Bug #22006](http://bugs.winehq.org/show_bug.cgi?id=22006 "OpenProcess does not enforce ACL"))
|
||||
* Return correct IMediaSeeking stream positions in quartz ([Wine Bug #23174](http://bugs.winehq.org/show_bug.cgi?id=23174 "Fallout 3: Diologue and Video/sound issues"))
|
||||
* Add implementation of WTSEnumerateProcessesW ([Wine Bug #29903](http://bugs.winehq.org/show_bug.cgi?id=29903 "Some Microsoft debuggers fail to enumerate processes due to wtsapi32.WTSEnumerateProcessesW() being a stub (Microsoft Visual Studio 2005, DbgCLR from .NET 2.0 SDK)"))
|
||||
* Fix race conditions and deadlocks in strmbase/quartz ([Wine Bug #31566](http://bugs.winehq.org/show_bug.cgi?id=31566 "Fallout 3: regression causes block at critical section when radio is enabled"))
|
||||
* Support for stored file ACLs ([Wine Bug #31858](http://bugs.winehq.org/show_bug.cgi?id=31858 "Netflix on Firefox fails with Internet Connection Problem when loading bar is at 99%"))
|
||||
* Implement an Arial replacement font ([Wine Bug #32323](http://bugs.winehq.org/show_bug.cgi?id=32323 "Netflix (Silverlight 4.x) and several .NET Framework 3.x/4.0 WPF apps require either Arial or Verdana to be installed"))
|
||||
* Support for interface change notifications ([Wine Bug #32328](http://bugs.winehq.org/show_bug.cgi?id=32328 "Many .NET and Silverlight applications require SIO_ADDRESS_LIST_CHANGE for interface change notifications"))
|
||||
* Support for inherited file ACLs ([Wine Bug #34406](http://bugs.winehq.org/show_bug.cgi?id=34406 "Finale Notepad 2012 doesn't copy/create user files on program start"))
|
||||
|
||||
Besides that the following additional changes are included:
|
||||
|
||||
* Support for interface change notifications ([Wine Bug #32328](http://bugs.winehq.org/show_bug.cgi?id=32328))
|
||||
* Support for stored file ACLs ([Wine Bug #31858](http://bugs.winehq.org/show_bug.cgi?id=31858))
|
||||
* Support for inherited file ACLs ([Wine Bug #34406](http://bugs.winehq.org/show_bug.cgi?id=34406))
|
||||
* Support for Junction Points ([Wine Bug #12401](http://bugs.winehq.org/show_bug.cgi?id=12401))
|
||||
* Support for TransmitFile ([Wine Bug #5048](http://bugs.winehq.org/show_bug.cgi?id=5048))
|
||||
* Support for GetVolumePathName
|
||||
* Implement an Arial replacement font ([Wine Bug #32323](http://bugs.winehq.org/show_bug.cgi?id=32323))
|
||||
* Workaround for TransactNamedPipe not being supported ([Wine Bug #17273](http://bugs.winehq.org/show_bug.cgi?id=17273))
|
||||
* Fix incorrect scaling for DECIMAL values in VarDecAdd ([Wine Bug #31269](http://bugs.winehq.org/show_bug.cgi?id=31269))
|
||||
* Return NULL-terminated list of arguments in CommandLineToArgvW ([Wine Bug #22829](http://bugs.winehq.org/show_bug.cgi?id=22829))
|
||||
* XEMBED support for embedding Wine windows inside Linux applications
|
||||
* Reduced SetTimer minimum value from 15 ms to 5 ms (improves Silverlight framerates)
|
||||
* Lockfree algorithm for filedescriptor cache (improves file access speed)
|
||||
* Workaround for shlwapi URLs with relative paths
|
||||
* Support for PulseAudio backend for audio
|
||||
* Other Pipelight specific enhancements
|
||||
* Reduced SetTimer minimum value from 15 ms to 5 ms (improves Silverlight framerates)
|
||||
* Support for GetVolumePathName
|
||||
* Support for PulseAudio backend for audio
|
||||
* Workaround for shlwapi URLs with relative paths
|
||||
* XEMBED support for embedding Wine windows inside Linux applications
|
||||
|
||||
### Compiling wine-compholio
|
||||
|
||||
In order to wine-compholio, please use the recommended Makefile based approach which
|
||||
will automatically decide whether to use 'git apply' or 'gitapply.sh'. The following
|
||||
instructions (based on the [Gentoo Wiki](https://wiki.gentoo.org/wiki/Netflix/Pipelight#Compiling_manually))
|
||||
will give a short overview how to compile wine-compholio, but of course not explain
|
||||
details. Make sure to install all required wine dependencies before proceeding.
|
||||
|
||||
As the first step please grab the latest Wine source:
|
||||
```bash
|
||||
wget http://prdownloads.sourceforge.net/wine/wine-1.7.22.tar.bz2
|
||||
wget https://github.com/compholio/wine-compholio-daily/archive/v1.7.22.tar.gz
|
||||
```
|
||||
Extract the archives:
|
||||
```bash
|
||||
tar xvjf wine-1*.tar.bz2
|
||||
cd wine-1*
|
||||
tar xvzf ../v1.7.22.tar.gz --strip-components 1
|
||||
```
|
||||
And apply the patches:
|
||||
```bash
|
||||
make -C ./patches DESTDIR=$(pwd) install
|
||||
```
|
||||
Afterwards run configure (you can also specify a prefix if you don't want to install
|
||||
wine-compholio system-wide):
|
||||
```bash
|
||||
./configure --with-xattr
|
||||
```
|
||||
Before you continue you should make sure that ./configure doesn't show any warnings
|
||||
(look at the end of the output). If there are any warnings, this most likely means
|
||||
that you're missing some important header files. Install them and repeat the ./configure
|
||||
step until all problems are fixed.
|
||||
|
||||
Afterwards compile it (and grab a cup of coffee):
|
||||
```bash
|
||||
make
|
||||
```
|
||||
And install it (you only need sudo for a system-wide installation):
|
||||
```bash
|
||||
sudo make install
|
||||
```
|
||||
|
||||
### Excluding patches
|
||||
|
||||
It is also possible to apply only a subset of the patches, for example if you're compiling
|
||||
for a distribution where PulseAudio is not installed, or if you just don't like a specific
|
||||
patchset. Please note that some patchsets depend on each other, and requesting an impossible
|
||||
situation might result in a failure to apply all patches.
|
||||
|
||||
Lets assume you want to exclude the patchset in directory DIRNAME, then just invoke make like that:
|
||||
```bash
|
||||
make -C ./patches DESTDIR=$(pwd) install -W DIRNAME.ok
|
||||
```
|
||||
|
1
debian/changelog
vendored
1
debian/changelog
vendored
@ -1,4 +1,5 @@
|
||||
wine-compholio (1.7.23) UNRELEASED; urgency=low
|
||||
* Rewrite of patch system to simplify mainting large patchsets.
|
||||
* Fix failing Junction Point test.
|
||||
* Fix possible race conditions in strmbase/quartz.
|
||||
* Fix race condition between EndOfStream and Pause.
|
||||
|
112
debian/tools/gitapply.sh
vendored
112
debian/tools/gitapply.sh
vendored
@ -1,4 +1,23 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Wrapper to apply binary patches without git.
|
||||
#
|
||||
# Copyright (C) 2014 Sebastian Lackner
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
#
|
||||
|
||||
# Setup parser variables
|
||||
nogit=0
|
||||
@ -41,6 +60,12 @@ usage()
|
||||
echo ""
|
||||
}
|
||||
|
||||
gitsha1()
|
||||
{
|
||||
echo -en "blob $(du -b "$1" | cut -f1)\x00" | cat - "$1" | sha1sum | cut -d' ' -f1
|
||||
}
|
||||
|
||||
|
||||
# Parse environment variables
|
||||
while [[ $# > 0 ]]; do
|
||||
cmd="$1"; shift
|
||||
@ -62,7 +87,8 @@ while [[ $# > 0 ]]; do
|
||||
;;
|
||||
|
||||
-R)
|
||||
abort "Reverse applying patches not supported yet with this patch tool."
|
||||
echo "Reverse applying patches not supported yet with this tool." >&2
|
||||
exit 1
|
||||
;;
|
||||
|
||||
--help)
|
||||
@ -82,10 +108,19 @@ if [ "$nogit" -eq 0 ] && command -v git >/dev/null 2>&1; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check for missing depdencies
|
||||
for dependency in awk chmod cut dd du gzip hexdump patch sha1sum; do
|
||||
if ! command -v "$dependency" >/dev/null 2>&1; then
|
||||
echo "Missing dependency: $dependency - please install this program and try again." >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# Detect BSD
|
||||
if gzip -V 2>&1 | grep "BSD" &> /dev/null; then
|
||||
echo "This script is not compatible with *BSD utilities." >&2
|
||||
echo "Please install git, which provides the same functionality and will be used instead." >&2
|
||||
exit 1;
|
||||
echo "This script is not compatible with *BSD utilities. Please install git," >&2
|
||||
echo "which provides the same functionality and will be used instead." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Decode base85 git data, prepend with a gzip header
|
||||
@ -194,7 +229,7 @@ while IFS= read -r line; do
|
||||
echo "$line" >> "$patch_tmpfile"
|
||||
continue
|
||||
|
||||
elif [[ "$line" =~ ^old\ mode ]] || [[ "$line" =~ ^deleted\ file\ mode ]]; then
|
||||
elif [ "${line:0:8}" == "old mode" ] || [ "${line:0:17}" == "deleted file mode" ]; then
|
||||
# ignore
|
||||
echo "$line" >> "$patch_tmpfile"
|
||||
continue
|
||||
@ -204,31 +239,25 @@ while IFS= read -r line; do
|
||||
echo "$line" >> "$patch_tmpfile"
|
||||
continue
|
||||
|
||||
elif [[ "$line" =~ ^new\ mode ]] || [[ "$line" =~ ^new\ file\ mode ]]; then
|
||||
patch_errors+=("$lineno: unable to parse header line '$line'")
|
||||
elif [ "${line:0:8}" == "new mode" ] || [ "${line:0:13}" == "new file mode" ]; then
|
||||
patch_errors+=("$lineno: Unable to parse header line '$line'.")
|
||||
patch_invalid=1
|
||||
echo "$line" >> "$patch_tmpfile"
|
||||
continue
|
||||
|
||||
elif [[ "$line" =~ ^copy\ from ]] || [[ "$line" =~ ^copy\ to ]]; then
|
||||
patch_errors+=("$lineno: copy header not implemented yet")
|
||||
elif [ "${line:0:9}" == "copy from" ] || [ "${line:0:7}" == "copy to" ]; then
|
||||
patch_errors+=("$lineno: Copy header not implemented yet.")
|
||||
patch_invalid=1
|
||||
echo "$line" >> "$patch_tmpfile"
|
||||
continue
|
||||
|
||||
elif [[ "$line" =~ ^rename\ old ]] || [[ "$line" =~ ^rename\ from ]]; then
|
||||
patch_errors+=("$lineno: rename header not implemented yet")
|
||||
elif [ "${line:0:7}" == "rename " ]; then
|
||||
patch_errors+=("$lineno: Patch rename header not implemented yet.")
|
||||
patch_invalid=1
|
||||
echo "$line" >> "$patch_tmpfile"
|
||||
continue
|
||||
|
||||
elif [[ "$line" =~ ^rename\ new ]] || [[ "$line" =~ ^rename\ to ]]; then
|
||||
patch_errors+=("$lineno: rename header not implemented yet")
|
||||
patch_invalid=1
|
||||
echo "$line" >> "$patch_tmpfile"
|
||||
continue
|
||||
|
||||
elif [[ "$line" =~ ^similarity\ index ]] || [[ "$line" =~ ^dissimilarity\ index ]]; then
|
||||
elif [ "${line:0:16}" == "similarity index" ] || [ "${line:0:19}" == "dissimilarity index" ]; then
|
||||
# ignore
|
||||
echo "$line" >> "$patch_tmpfile"
|
||||
continue
|
||||
@ -239,8 +268,8 @@ while IFS= read -r line; do
|
||||
echo "$line" >> "$patch_tmpfile"
|
||||
continue
|
||||
|
||||
elif [[ "$line" =~ ^index\ ]]; then
|
||||
patch_errors+=("$lineno: unable to parse header line '$line'")
|
||||
elif [ "${line:0:6}" == "index " ]; then
|
||||
patch_errors+=("$lineno: Unable to parse header line '$line'.")
|
||||
patch_invalid=1
|
||||
echo "$line" >> "$patch_tmpfile"
|
||||
continue
|
||||
@ -250,12 +279,12 @@ while IFS= read -r line; do
|
||||
if [[ "$patch_oldname" =~ ^a/(.*)$ ]]; then
|
||||
patch_oldname="${BASH_REMATCH[1]}"
|
||||
elif [ "$patch_oldname" != "/dev/null" ]; then
|
||||
abort "old name doesn't start with a/."
|
||||
abort "Old name doesn't start with a/."
|
||||
fi
|
||||
if [[ "$patch_newname" =~ ^b/(.*)$ ]]; then
|
||||
patch_newname="${BASH_REMATCH[1]}"
|
||||
elif [ "$patch_newname" != "/dev/null" ]; then
|
||||
abort "new name doesn't start with b/."
|
||||
abort "New name doesn't start with b/."
|
||||
fi
|
||||
|
||||
patch_mode=2
|
||||
@ -269,12 +298,12 @@ while IFS= read -r line; do
|
||||
if [[ "$line" == "GIT binary patch" ]]; then
|
||||
|
||||
if [ -z "$patch_oldsha1" ] || [ -z "$patch_newsha1" ]; then
|
||||
patch_errors+=("$lineno: missing index header, sha1 sums required for binary patch")
|
||||
patch_errors+=("$lineno: Missing index header, sha1 sums required for binary patch.")
|
||||
patch_invalid=1
|
||||
fi
|
||||
|
||||
if [ "$patch_oldname" != "$patch_newname" ]; then
|
||||
patch_errors+=("$lineno: stripped old- and new name doesn't match")
|
||||
patch_errors+=("$lineno: Stripped old- and new name doesn't match for binary patch.")
|
||||
patch_invalid=1
|
||||
fi
|
||||
|
||||
@ -286,7 +315,7 @@ while IFS= read -r line; do
|
||||
patch_mode=100
|
||||
continue
|
||||
|
||||
elif [[ "$line" =~ ^@@\ - ]]; then
|
||||
elif [ "${line:0:4}" == "@@ -" ]; then
|
||||
# We count the number of lines added/removed for informational purposes
|
||||
patch_total_add=0
|
||||
patch_total_rem=0
|
||||
@ -294,10 +323,10 @@ while IFS= read -r line; do
|
||||
patch_mode=200
|
||||
# fall-through
|
||||
|
||||
elif [[ "$line" =~ ^diff\ --git\ ]]; then
|
||||
elif [ "${line:0:11}" == "diff --git " ]; then
|
||||
|
||||
if [ "$patch_oldname" != "$patch_newname" ]; then
|
||||
patch_errors+=("$lineno: stripped old- and new name doesn't match")
|
||||
patch_errors+=("$lineno: Stripped old- and new name doesn't match.")
|
||||
patch_invalid=1
|
||||
fi
|
||||
|
||||
@ -328,7 +357,7 @@ while IFS= read -r line; do
|
||||
# Check shasum if its not a patch creating a new file
|
||||
if [ "$patch_oldsha1" != "0000000000000000000000000000000000000000" ] || [ "$binary_patch_type" == "delta" ] || [ -f "$patch_oldname" ]; then
|
||||
if [ -f "$patch_oldname" ]; then
|
||||
sha=$(echo -en "blob $(du -b "$patch_oldname" | cut -f1)\x00" | cat - "$patch_oldname" | sha1sum | cut -d' ' -f1)
|
||||
sha=$(gitsha1 "$patch_oldname")
|
||||
else
|
||||
sha="0000000000000000000000000000000000000000"
|
||||
fi
|
||||
@ -403,13 +432,13 @@ while IFS= read -r line; do
|
||||
while read cmd arg1 arg2; do
|
||||
if [ "$cmd" == "S" ]; then
|
||||
binary_patch_destsize="$arg2"
|
||||
if [ "$arg1" -ne "$(du -b "$patch_oldname" | cut -f 1)" ]; then break; fi
|
||||
[ "$arg1" -eq "$(du -b "$patch_oldname" | cut -f 1)" ] || break
|
||||
|
||||
elif [ "$cmd" == "1" ]; then
|
||||
if ! dd if="$patch_oldname" bs=1 skip="$arg1" count="$arg2" >> "$decoded_tmpfile" 2>/dev/null; then break; fi
|
||||
dd if="$patch_oldname" bs=1 skip="$arg1" count="$arg2" >> "$decoded_tmpfile" 2>/dev/null || break
|
||||
|
||||
elif [ "$cmd" == "2" ]; then
|
||||
if ! dd if="$patch_tmpfile" bs=1 skip="$arg1" count="$arg2" >> "$decoded_tmpfile" 2>/dev/null; then break; fi
|
||||
dd if="$patch_tmpfile" bs=1 skip="$arg1" count="$arg2" >> "$decoded_tmpfile" 2>/dev/null || break
|
||||
|
||||
elif [ "$cmd" == "E" ]; then
|
||||
binary_patch_complete=1
|
||||
@ -432,7 +461,7 @@ while IFS= read -r line; do
|
||||
fi
|
||||
|
||||
# Check shasum if its not a patch creating a new file
|
||||
sha=$(echo -en "blob $(du -b "$patch_tmpfile" | cut -f1)\x00" | cat - "$patch_tmpfile" | sha1sum | cut -d' ' -f1)
|
||||
sha=$(gitsha1 "$patch_tmpfile")
|
||||
if [ "$patch_newsha1" != "$sha" ]; then
|
||||
echo "$lineno: Expected $patch_newsha1" >&2
|
||||
echo "$lineno: Got $sha" >&2
|
||||
@ -440,7 +469,7 @@ while IFS= read -r line; do
|
||||
fi
|
||||
|
||||
if ! cp "$patch_tmpfile" "$patch_oldname"; then
|
||||
abort "Unable to replace original file"
|
||||
abort "Unable to replace original file."
|
||||
fi
|
||||
if [ ! -z "$patch_filemode" ]; then
|
||||
chmod "${patch_filemode: -3}" "$patch_oldname" # we ignore failures for now
|
||||
@ -471,6 +500,11 @@ while IFS= read -r line; do
|
||||
patch_mode=201
|
||||
continue
|
||||
|
||||
elif [ "${line:0:2}" == "\\ " ]; then
|
||||
# ignore
|
||||
echo "$line" >> "$patch_tmpfile"
|
||||
continue
|
||||
|
||||
else
|
||||
echo "patching $patch_newname"
|
||||
|
||||
@ -489,23 +523,23 @@ while IFS= read -r line; do
|
||||
# These lines are part of a hunk, append it
|
||||
echo "$line" >> "$patch_tmpfile"
|
||||
|
||||
if [ "$hunk_src_lines" -gt 0 ] && [ "$hunk_dst_lines" -gt 0 ] && [[ "$line" =~ ^\ ]]; then
|
||||
if [ "${line:0:1}" == " " ] && [ "$hunk_src_lines" -gt 0 ] && [ "$hunk_dst_lines" -gt 0 ]; then
|
||||
(( hunk_src_lines-- ))
|
||||
(( hunk_dst_lines-- ))
|
||||
|
||||
elif [ "$hunk_src_lines" -gt 0 ] && [[ "$line" =~ ^- ]]; then
|
||||
elif [ "${line:0:1}" == "-" ] && [ "$hunk_src_lines" -gt 0 ]; then
|
||||
(( hunk_src_lines-- ))
|
||||
(( patch_total_rem++ ))
|
||||
|
||||
elif [ "$hunk_dst_lines" -gt 0 ] && [[ "$line" =~ ^\+ ]]; then
|
||||
elif [ "${line:0:1}" == "+" ] && [ "$hunk_dst_lines" -gt 0 ]; then
|
||||
(( hunk_dst_lines-- ))
|
||||
(( patch_total_add++ ))
|
||||
|
||||
elif [[ "$line" =~ ^\\\ ]]; then
|
||||
elif [ "${line:0:2}" == "\\ " ]; then
|
||||
continue # ignore "\\ No newline ..."
|
||||
|
||||
else
|
||||
abort "Unexpected line in hunk"
|
||||
abort "Unexpected line in hunk."
|
||||
fi
|
||||
|
||||
# If it was the last line of this hunk then go back to mode 200
|
||||
@ -544,7 +578,7 @@ while IFS= read -r line; do
|
||||
patch_mode=1
|
||||
continue
|
||||
|
||||
elif [[ "$line" =~ ^@@\ - ]] || [[ "$line" =~ ^---\ ]] || [[ "$line" =~ ^\+\+\+\ ]]; then
|
||||
elif [ "${line:0:4}" == "@@ -" ] || [ "${line:0:4}" == "--- " ] || [ "${line:0:4}" == "+++ " ]; then
|
||||
abort "Patch corrupted or not created with git."
|
||||
fi
|
||||
fi
|
||||
|
@ -1,21 +1,5 @@
|
||||
#!/bin/sh
|
||||
PATCH_DATA="";
|
||||
|
||||
for FILE in patches/*/*.def; do
|
||||
UUID=$(echo "${FILE}" | sed -e 's|^.*/||g' -e 's|\.def$||g');
|
||||
REVISION=$(cat "${FILE}" | sed -n 's|Revision: \(.*\)|\1|p');
|
||||
AUTHOR=$(cat "${FILE}" | sed -n 's|Author: \(.*\)|\1|p');
|
||||
TITLE=$(cat "${FILE}" | sed -n 's|Title: \(.*\)|\1|p');
|
||||
if [ "${AUTHOR}" = "" ] && [ "${TITLE}" = "" ]; then
|
||||
continue;
|
||||
fi
|
||||
if [ "${PATCH_DATA}" != "" ]; then
|
||||
PATCH_DATA="${PATCH_DATA}
|
||||
";
|
||||
fi
|
||||
PATCH_DATA="${PATCH_DATA}+ { \"${UUID}:${REVISION}\", \"${AUTHOR}\", \"${TITLE}\" },";
|
||||
done
|
||||
|
||||
PATCH_DATA=$(cat);
|
||||
PATCH_LINES=$(echo "${PATCH_DATA}" | wc -l);
|
||||
PATCH_LINES=$((${PATCH_LINES}+20));
|
||||
|
570
debian/tools/patchupdate.py
vendored
Executable file
570
debian/tools/patchupdate.py
vendored
Executable file
File diff suppressed because it is too large
Load Diff
320
debian/tools/patchutils.py
vendored
Normal file
320
debian/tools/patchutils.py
vendored
Normal file
@ -0,0 +1,320 @@
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# Python functions to read, split and apply patches.
|
||||
#
|
||||
# Copyright (C) 2014 Sebastian Lackner
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
#
|
||||
|
||||
import collections
|
||||
import difflib
|
||||
import hashlib
|
||||
import itertools
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import tempfile
|
||||
|
||||
class PatchParserError(RuntimeError):
|
||||
"""Unable to parse patch file - either an unimplemented feature, or corrupted patch."""
|
||||
pass
|
||||
|
||||
class PatchApplyError(RuntimeError):
|
||||
"""Failed to apply/merge patch."""
|
||||
pass
|
||||
|
||||
class PatchObject(object):
|
||||
def __init__(self, filename):
|
||||
self.extracted_patch = None
|
||||
self.unique_hash = None
|
||||
|
||||
self.filename = filename
|
||||
self.offset_begin = None
|
||||
self.offset_end = None
|
||||
self.isbinary = False
|
||||
|
||||
self.oldname = None
|
||||
self.newname = None
|
||||
self.modified_file = None
|
||||
|
||||
self.oldsha1 = None
|
||||
self.newsha1 = None
|
||||
self.newmode = None
|
||||
|
||||
def is_binary(self):
|
||||
return self.isbinary
|
||||
|
||||
def read_chunks(self):
|
||||
"""Iterates over arbitrary sized chunks of this patch."""
|
||||
assert self.offset_end >= self.offset_begin
|
||||
with open(self.filename) as fp:
|
||||
fp.seek(self.offset_begin)
|
||||
i = self.offset_end - self.offset_begin
|
||||
while i > 0:
|
||||
buf = fp.read(4096 if i > 4096 else i)
|
||||
if buf == "": raise IOError("Unable to extract patch.")
|
||||
yield buf
|
||||
i -= len(buf)
|
||||
|
||||
def extract(self):
|
||||
"""Create a temporary file containing the extracted patch."""
|
||||
if not self.extracted_patch:
|
||||
self.extracted_patch = tempfile.NamedTemporaryFile()
|
||||
for chunk in self.read_chunks():
|
||||
self.extracted_patch.write(chunk)
|
||||
self.extracted_patch.flush()
|
||||
return self.extracted_patch
|
||||
|
||||
def hash(self):
|
||||
"""Hash the content of the patch."""
|
||||
if not self.unique_hash:
|
||||
m = hashlib.sha256()
|
||||
for chunk in self.read_chunks():
|
||||
m.update(chunk)
|
||||
self.unique_hash = m.digest()
|
||||
return self.unique_hash
|
||||
|
||||
def read_patch(filename):
|
||||
"""Iterates over all patches contained in a file, and returns PatchObject objects."""
|
||||
|
||||
class _FileReader(object):
|
||||
def __init__(self, filename):
|
||||
self.filename = filename
|
||||
self.fp = open(self.filename)
|
||||
self.peeked = None
|
||||
|
||||
def close(self):
|
||||
self.fp.close()
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, type, value, traceback):
|
||||
self.close()
|
||||
|
||||
def seek(self, pos):
|
||||
"""Change the file cursor position."""
|
||||
self.fp.seek(pos)
|
||||
self.peeked = None
|
||||
|
||||
def tell(self):
|
||||
"""Return the current file cursor position."""
|
||||
if self.peeked is None:
|
||||
return self.fp.tell()
|
||||
return self.peeked[0]
|
||||
|
||||
def peek(self):
|
||||
"""Read one line without changing the file cursor."""
|
||||
if self.peeked is None:
|
||||
pos = self.fp.tell()
|
||||
tmp = self.fp.readline()
|
||||
if len(tmp) == 0: return None
|
||||
self.peeked = (pos, tmp)
|
||||
return self.peeked[1]
|
||||
|
||||
def read(self):
|
||||
"""Read one line from the file, and move the file cursor to the next line."""
|
||||
if self.peeked is None:
|
||||
tmp = self.fp.readline()
|
||||
if len(tmp) == 0: return None
|
||||
return tmp
|
||||
tmp, self.peeked = self.peeked, None
|
||||
return tmp[1]
|
||||
|
||||
def _read_single_patch(fp, oldname=None, newname=None):
|
||||
"""Internal function to read a single patch from a file."""
|
||||
|
||||
patch = PatchObject(fp.filename)
|
||||
patch.offset_begin = fp.tell()
|
||||
patch.oldname = oldname
|
||||
patch.newname = newname
|
||||
|
||||
# Skip over initial diff --git header
|
||||
line = fp.peek()
|
||||
if line.startswith("diff --git "):
|
||||
assert fp.read() == line
|
||||
|
||||
# Read header
|
||||
while True:
|
||||
line = fp.peek()
|
||||
if line is None:
|
||||
break
|
||||
elif line.startswith("--- "):
|
||||
patch.oldname = line[4:].strip()
|
||||
elif line.startswith("+++ "):
|
||||
patch.newname = line[4:].strip()
|
||||
elif line.startswith("old mode") or line.startswith("deleted file mode"):
|
||||
pass # ignore
|
||||
elif line.startswith("new mode "):
|
||||
patch.newmode = line[9:].strip()
|
||||
elif line.startswith("new file mode "):
|
||||
patch.newmode = line[14:].strip()
|
||||
elif line.startswith("new mode") or line.startswith("new file mode"):
|
||||
raise PatchParserError("Unable to parse header line '%s'." % line)
|
||||
elif line.startswith("copy from") or line.startswith("copy to"):
|
||||
raise NotImplementedError("Patch copy header not implemented yet.")
|
||||
elif line.startswith("rename "):
|
||||
raise NotImplementedError("Patch rename header not implemented yet.")
|
||||
elif line.startswith("similarity index") or line.startswith("dissimilarity index"):
|
||||
pass # ignore
|
||||
elif line.startswith("index "):
|
||||
r = re.match("^index ([a-fA-F0-9]*)\.\.([a-fA-F0-9]*)", line)
|
||||
if not r: raise PatchParserError("Unable to parse index header line '%s'." % line)
|
||||
patch.oldsha1, patch.newsha1 = r.group(1), r.group(2)
|
||||
else:
|
||||
break
|
||||
assert fp.read() == line
|
||||
|
||||
if patch.oldname is None or patch.newname is None:
|
||||
raise PatchParserError("Missing old or new name.")
|
||||
elif patch.oldname == "/dev/null" and patch.newname == "/dev/null":
|
||||
raise PatchParserError("Old and new name is /dev/null?")
|
||||
|
||||
if patch.oldname.startswith("a/"):
|
||||
patch.oldname = patch.oldname[2:]
|
||||
elif patch.oldname != "/dev/null":
|
||||
raise PatchParserError("Old name in patch doesn't start with a/.")
|
||||
|
||||
if patch.newname.startswith("b/"):
|
||||
patch.newname = patch.newname[2:]
|
||||
elif patch.newname != "/dev/null":
|
||||
raise PatchParserError("New name in patch doesn't start with b/.")
|
||||
|
||||
if patch.newname != "/dev/null":
|
||||
patch.modified_file = patch.newname
|
||||
else:
|
||||
patch.modified_file = patch.oldname
|
||||
|
||||
# Decide between binary and textual patch
|
||||
if line is None or line.startswith("diff --git ") or line.startswith("--- "):
|
||||
if oldname != newname:
|
||||
raise PatchParserError("Stripped old- and new name doesn't match.")
|
||||
|
||||
elif line.startswith("@@ -"):
|
||||
while True:
|
||||
line = fp.peek()
|
||||
if line is None or not line.startswith("@@ -"):
|
||||
break
|
||||
|
||||
r = re.match("^@@ -(([0-9]+),)?([0-9]+) \+(([0-9]+),)?([0-9]+) @@", line)
|
||||
if not r: raise PatchParserError("Unable to parse hunk header '%s'." % line)
|
||||
srcpos = max(int(r.group(2)) - 1, 0) if r.group(2) else 0
|
||||
dstpos = max(int(r.group(5)) - 1, 0) if r.group(5) else 0
|
||||
srclines, dstlines = int(r.group(3)), int(r.group(6))
|
||||
if srclines <= 0 and dstlines <= 0:
|
||||
raise PatchParserError("Empty hunk doesn't make sense.")
|
||||
assert fp.read() == line
|
||||
|
||||
while srclines > 0 or dstlines > 0:
|
||||
line = fp.read()
|
||||
if line is None:
|
||||
raise PatchParserError("Truncated patch.")
|
||||
elif line.startswith(" "):
|
||||
if srclines == 0 or dstlines == 0:
|
||||
raise PatchParserError("Corrupted patch.")
|
||||
srclines -= 1
|
||||
dstlines -= 1
|
||||
elif line.startswith("-"):
|
||||
if srclines == 0:
|
||||
raise PatchParserError("Corrupted patch.")
|
||||
srclines -= 1
|
||||
elif line.startswith("+"):
|
||||
if dstlines == 0:
|
||||
raise PatchParserError("Corrupted patch.")
|
||||
dstlines -= 1
|
||||
elif line.startswith("\\ "):
|
||||
pass # ignore
|
||||
else:
|
||||
raise PatchParserError("Unexpected line in hunk.")
|
||||
|
||||
while True:
|
||||
line = fp.peek()
|
||||
if line is None or not line.startswith("\\ "): break
|
||||
assert fp.read() == line
|
||||
|
||||
elif line.rstrip() == "GIT binary patch":
|
||||
if patch.oldsha1 is None or patch.newsha1 is None:
|
||||
raise PatchParserError("Missing index header, sha1 sums required for binary patch.")
|
||||
elif patch.oldname != patch.newname:
|
||||
raise PatchParserError("Stripped old- and new name doesn't match for binary patch.")
|
||||
assert fp.read() == line
|
||||
|
||||
line = fp.read()
|
||||
if line is None: raise PatchParserError("Unexpected end of file.")
|
||||
r = re.match("^(literal|delta) ([0-9]+)", line)
|
||||
if not r: raise NotImplementedError("Only literal/delta patches are supported.")
|
||||
patch.isbinary = True
|
||||
|
||||
# Skip over patch data
|
||||
while True:
|
||||
line = fp.read()
|
||||
if line is None or line.strip() == "":
|
||||
break
|
||||
|
||||
else:
|
||||
raise PatchParserError("Unknown patch format.")
|
||||
|
||||
patch.offset_end = fp.tell()
|
||||
return patch
|
||||
|
||||
with _FileReader(filename) as fp:
|
||||
while True:
|
||||
line = fp.peek()
|
||||
if line is None:
|
||||
break
|
||||
elif line.startswith("diff --git "):
|
||||
tmp = line.strip().split(" ")
|
||||
if len(tmp) != 4: raise PatchParserError("Unable to parse git diff header line '%s'." % line)
|
||||
yield _read_single_patch(fp, tmp[2].strip(), tmp[3].strip())
|
||||
elif line.startswith("--- "):
|
||||
yield _read_single_patch(fp)
|
||||
elif line.startswith("@@ -") or line.startswith("+++ "):
|
||||
raise PatchParserError("Patch didn't start with a git or diff header.")
|
||||
else:
|
||||
assert fp.read() == line
|
||||
|
||||
def apply_patch(content, patches, reverse=False, fuzz=2):
|
||||
"""Apply a patch with optional fuzz - uses the commandline 'patch' utility."""
|
||||
|
||||
if not isinstance(patches, collections.Sequence):
|
||||
patches = [patches]
|
||||
|
||||
contentfile = tempfile.NamedTemporaryFile(delete=False)
|
||||
try:
|
||||
contentfile.write(content)
|
||||
contentfile.close()
|
||||
|
||||
for patch in patches:
|
||||
|
||||
patchfile = patch.extract()
|
||||
cmdline = ["patch", "--batch", "--silent", "-r", "-"]
|
||||
if reverse: cmdline.append("--reverse")
|
||||
if fuzz != 2: cmdline.append("--fuzz=%d" % fuzz)
|
||||
cmdline += [contentfile.name, patchfile.name]
|
||||
|
||||
with open(os.devnull, 'w') as devnull:
|
||||
exitcode = subprocess.call(cmdline, stdout=devnull, stderr=devnull)
|
||||
if exitcode != 0:
|
||||
raise PatchApplyError("Failed to apply patch (exitcode %d)." % exitcode)
|
||||
|
||||
with open(contentfile.name) as fp:
|
||||
content = fp.read()
|
||||
|
||||
finally:
|
||||
os.unlink(contentfile.name)
|
||||
|
||||
return content
|
||||
|
@ -1,3 +0,0 @@
|
||||
Revision: 1
|
||||
Author: Sebastian Lackner
|
||||
Title: Add commandline option --patches to show the patch list.
|
@ -1,3 +0,0 @@
|
||||
Revision: 1
|
||||
Author: Michael Müller
|
||||
Title: Add commandline option --check-libs to test if shared libraries are installed.
|
7
patches/00-Commandline/definition
Normal file
7
patches/00-Commandline/definition
Normal file
@ -0,0 +1,7 @@
|
||||
Author: Sebastian Lackner
|
||||
Subject: Add commandline option --patches to show the patch list.
|
||||
Revision: 1
|
||||
|
||||
Author: Michael Müller
|
||||
Subject: Add commandline option --check-libs to test if shared libraries are installed.
|
||||
Revision: 1
|
@ -1,3 +0,0 @@
|
||||
Revision: 2
|
||||
Author: Erich E. Hoover
|
||||
Title: Implement SIO_ADDRESS_LIST_CHANGE.
|
4
patches/01-Address_Change_Notification/definition
Normal file
4
patches/01-Address_Change_Notification/definition
Normal file
@ -0,0 +1,4 @@
|
||||
Author: Erich E. Hoover
|
||||
Subject: Implement SIO_ADDRESS_LIST_CHANGE.
|
||||
Revision: 2
|
||||
Fixes: [32328] Support for interface change notifications
|
@ -1,3 +0,0 @@
|
||||
Revision: 6
|
||||
Author: Erich E. Hoover
|
||||
Title: Store and return security attributes with extended file attributes.
|
5
patches/02-ACL_Extended_Attributes/definition
Normal file
5
patches/02-ACL_Extended_Attributes/definition
Normal file
@ -0,0 +1,5 @@
|
||||
Author: Erich E. Hoover
|
||||
Subject: Store and return security attributes with extended file attributes.
|
||||
Revision: 6
|
||||
Fixes: [31858] Support for stored file ACLs
|
||||
Fixes: [34406] Support for inherited file ACLs
|
@ -1,3 +0,0 @@
|
||||
Revision: 1
|
||||
Author: Sebastian Lackner
|
||||
Title: Enable/disable windows when they are (un)mapped by foreign applications.
|
@ -1,3 +0,0 @@
|
||||
Revision: 1
|
||||
Author: Sebastian Lackner
|
||||
Title: Update gl_drawable for embedded windows.
|
9
patches/04-XEMBED/definition
Normal file
9
patches/04-XEMBED/definition
Normal file
@ -0,0 +1,9 @@
|
||||
Author: Sebastian Lackner
|
||||
Subject: Enable/disable windows when they are (un)mapped by foreign applications.
|
||||
Revision: 1
|
||||
|
||||
Author: Sebastian Lackner
|
||||
Subject: Update gl_drawable for embedded windows.
|
||||
Revision: 1
|
||||
|
||||
Fixes: XEMBED support for embedding Wine windows inside Linux applications
|
@ -1,4 +0,0 @@
|
||||
Revision: 1
|
||||
Author: Sebastian Lackner
|
||||
Title: Change return value of stub SetNamedPipeHandleState to TRUE.
|
||||
|
5
patches/05-Named_Pipe/definition
Normal file
5
patches/05-Named_Pipe/definition
Normal file
@ -0,0 +1,5 @@
|
||||
Author: Sebastian Lackner
|
||||
Subject: Change return value of stub SetNamedPipeHandleState to TRUE.
|
||||
Revision: 1
|
||||
|
||||
Fixes: [17273] Workaround for TransactNamedPipe not being supported
|
@ -1,7 +1,7 @@
|
||||
From 8cb75a25d71c1ea659ce69fa74f725cd9b9a64f0 Mon Sep 17 00:00:00 2001
|
||||
From 9c64dcb14a77b7b1835bb06e03c90c502a1109f0 Mon Sep 17 00:00:00 2001
|
||||
From: Maarten Lankhorst <maarten.lankhorst@canonical.com>
|
||||
Date: Sat, 8 Feb 2014 16:08:53 +0100
|
||||
Subject: [PATCH 08/42] winmm: Load winealsa if winepulse is found
|
||||
Date: Tue, 24 Jun 2014 08:48:45 +0200
|
||||
Subject: [PATCH 08/43] winmm: Load winealsa if winepulse is found
|
||||
|
||||
Fixes midi on winepulse
|
||||
---
|
||||
@ -25,5 +25,5 @@ index c3b3674..56cfe35 100644
|
||||
HeapFree(GetProcessHeap(), 0, drvA);
|
||||
PropVariantClear(&pv);
|
||||
--
|
||||
1.8.5.2
|
||||
2.0.0
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user