mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
patchinstall.py: Bring up to patchinstall.sh.
I think as of this commit it's feature-complete, minus a couple things I'm not sure we still care about.
This commit is contained in:
parent
732ab97a7e
commit
f36c844f11
@ -1,41 +1,71 @@
|
||||
#!/usr/bin/env python2
|
||||
|
||||
import getopt, os, subprocess, sys
|
||||
# Copyright (C) 2020 Zebediah Figura
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
patchdir = os.path.dirname(os.path.realpath(__file__)) + '/../patches/'
|
||||
import email.header, getopt, os, subprocess, sys, tempfile
|
||||
|
||||
stagingdir = os.path.dirname(os.path.realpath(__file__)) + '/../'
|
||||
patchdir = stagingdir + 'patches'
|
||||
if 'DESTDIR' in os.environ:
|
||||
winedir = os.environ['DESTDIR']
|
||||
else:
|
||||
winedir = '.'
|
||||
backend = "patch"
|
||||
force_autoconf = False
|
||||
|
||||
applied = []
|
||||
|
||||
patch_data = ''
|
||||
|
||||
def usage():
|
||||
print '''
|
||||
Usage: ./staging/patchinstall.py [DESTDIR=path] [options] [patchset ...]
|
||||
|
||||
Applies every patch to a Wine tree.
|
||||
Applies all Wine-Staging patch sets, or each specified patch set plus its
|
||||
dependencies, to a Wine tree.
|
||||
|
||||
Options:
|
||||
-h, --help print this message
|
||||
--all apply all patches (except those excluded with -W)
|
||||
-W <patchset> exclude a patch
|
||||
--no-autoconf do not run autoconf and tools/make_requests
|
||||
--backend=<backend> use the given backend to apply patches:
|
||||
patch use the `gitapply.sh` tool (a wrapper around `patch`)
|
||||
git-am use `git am`
|
||||
git-am-C1 use `git am -C1`
|
||||
git-apply use `git apply`
|
||||
-r, --rebase-mode alias for --backend=git-am-C1 --no-autoconf
|
||||
-h, --help print this message
|
||||
-v, --version print version information
|
||||
-a, --all apply all patches (except those excluded with -W)
|
||||
-W, --exclude <patchset> exclude a patch
|
||||
--no-autoconf do not run autoreconf and tools/make_requests
|
||||
--force-autoconf run autoreconf and tools/make_requests after every patch
|
||||
(ignored when not using git-am or git-am-C1 backends)
|
||||
--backend=<backend> use the given backend to apply patches:
|
||||
patch use the `gitapply.sh` tool (a wrapper around `patch`)
|
||||
git-am use `git am`
|
||||
git-am-C1 use `git am -C1`
|
||||
git-apply use `git apply`
|
||||
--no-patchlist do not generate a patch list (needed for `wine --patches`)
|
||||
-r, --rebase-mode alias for --backend=git-am-C1 --no-autoconf --no-patchlist
|
||||
'''
|
||||
|
||||
def run(*args, **kwargs):
|
||||
print ' '.join(args[0])
|
||||
return subprocess.call(*args, **kwargs)
|
||||
|
||||
# return a patch to be shoved in patchlist below
|
||||
def parse_def_file(name, path):
|
||||
deps = []
|
||||
if os.path.exists(path):
|
||||
with open(path) as z:
|
||||
for l in z.readlines():
|
||||
with open(path) as f:
|
||||
for l in f.readlines():
|
||||
if l.lower().startswith('depends: '):
|
||||
deps.append(l.split(' ')[1].strip())
|
||||
elif l.lower().strip() == 'disabled: true':
|
||||
@ -44,14 +74,54 @@ def parse_def_file(name, path):
|
||||
|
||||
def apply_patch(patch):
|
||||
if backend == 'git-am':
|
||||
return subprocess.call(['git','-C',winedir,'am',patch])
|
||||
return run(['git','-C',winedir,'am',patch])
|
||||
elif backend == 'git-am-C1':
|
||||
return subprocess.call(['git','-C',winedir,'am','-C1',patch])
|
||||
return run(['git','-C',winedir,'am','-C1',patch])
|
||||
elif backend == 'patch':
|
||||
with open(patch) as f:
|
||||
print patchdir+'/gitapply.sh <',patch
|
||||
return subprocess.call([patchdir+'/gitapply.sh'],stdin=f)
|
||||
elif backend == 'git-apply':
|
||||
return subprocess.call(['git','-C',winedir,'apply','--index',patch])
|
||||
return run(['git','-C',winedir,'apply','--index',patch])
|
||||
|
||||
def run_autoconf(patch):
|
||||
if not force_autoconf: return
|
||||
|
||||
if backend != 'git-am' and backend != 'git-am-C1':
|
||||
print 'Warning: ignoring --force-autoconf for backend ',backend
|
||||
|
||||
need_autoreconf = False
|
||||
need_make_requests = False
|
||||
|
||||
with open(patch) as f:
|
||||
for line in f.readlines():
|
||||
line = line.strip()
|
||||
if line == '--- a/configure.ac' or line == '--- a/aclocal.m4': need_autoreconf = True
|
||||
elif line == '--- a/server/protocol.def': need_make_requests = True
|
||||
|
||||
if need_autoreconf:
|
||||
run(['autoreconf','-f'], cwd=winedir)
|
||||
if need_make_requests:
|
||||
run(['./tools/make_requests'], cwd=winedir)
|
||||
if need_autoreconf or need_make_requests:
|
||||
run(['git','-C',winedir,'commit','-a','--amend','--no-edit'])
|
||||
|
||||
def add_patch_data(patch):
|
||||
global patch_data
|
||||
author = ''
|
||||
subject = ''
|
||||
with open(patch) as f:
|
||||
for line in f.readlines():
|
||||
header = email.header.decode_header(line)
|
||||
if header[0][0] == 'From:':
|
||||
author = header[1][0]
|
||||
elif line[:5] == 'From:':
|
||||
author = line[6:line.index('<')-1]
|
||||
elif line[:8] == 'Subject:':
|
||||
subject = line[9:].rstrip()
|
||||
if '[' in subject: subject = subject[subject.index(']') + 1:]
|
||||
if author and subject: break
|
||||
patch_data += '+ {"%s", "%s", 1},\n' %(author, subject)
|
||||
|
||||
def apply_set(patchlist, name):
|
||||
if name in applied:
|
||||
@ -59,11 +129,14 @@ def apply_set(patchlist, name):
|
||||
for dep in patchlist[name]:
|
||||
if not apply_set(patchlist, dep):
|
||||
return False
|
||||
print 'Applying',name
|
||||
for patch in sorted(os.listdir(patchdir+'/'+name)):
|
||||
if patch.endswith('.patch') and patch.startswith('0') and apply_patch(patchdir+'/'+name+'/'+patch):
|
||||
print 'Failed to apply patch %s/%s' %(name, patch)
|
||||
return False
|
||||
if patch.endswith('.patch') and patch.startswith('0'):
|
||||
patch_file = patchdir + '/' + name + '/' + patch
|
||||
if apply_patch(patch_file):
|
||||
print 'Failed to apply patch %s/%s' %(name, patch)
|
||||
return False
|
||||
run_autoconf(patch_file)
|
||||
add_patch_data(patch_file)
|
||||
applied.append(name)
|
||||
return True
|
||||
|
||||
@ -77,15 +150,58 @@ def add_patchset(patchlist, name):
|
||||
patchlist[name] = deps
|
||||
for dep in deps: add_patchset(patchlist, dep)
|
||||
|
||||
def generate_patchlist(patchlist):
|
||||
with tempfile.NamedTemporaryFile(mode='w') as f:
|
||||
f.write('''From: Wine Staging Team <webmaster@fds-team.de>
|
||||
Subject: Autogenerated patch list.
|
||||
|
||||
diff --git a/libs/wine/config.c b/libs/wine/config.c
|
||||
index 5262c76..0a3182f 100644
|
||||
--- a/libs/wine/config.c
|
||||
+++ b/libs/wine/config.c
|
||||
@@ -478,10 +478,''' + str(21 + patch_data.count('\n')) + ''' @@ const char *wine_get_version(void)
|
||||
return PACKAGE_VERSION;
|
||||
}
|
||||
|
||||
+static const struct
|
||||
+{
|
||||
+ const char *author;
|
||||
+ const char *subject;
|
||||
+ int revision;
|
||||
+}
|
||||
+wine_patch_data[] =
|
||||
+{
|
||||
''' + patch_data + '''+ {NULL, NULL, 0}
|
||||
+};
|
||||
+
|
||||
/* return the applied non-standard patches */
|
||||
const void *wine_get_patches(void)
|
||||
{
|
||||
- return NULL;
|
||||
+ return &wine_patch_data[0];
|
||||
}
|
||||
|
||||
/* return the build id string */
|
||||
''')
|
||||
f.flush()
|
||||
apply_patch(f.name)
|
||||
|
||||
def main():
|
||||
global backend
|
||||
global backend, force_autoconf
|
||||
patchlist = {}
|
||||
excluded = []
|
||||
no_autoconf = False
|
||||
force_autoconf = False
|
||||
no_patchlist = False
|
||||
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], 'hrW:', ['all', 'backend', 'help', 'no-autoconf'])
|
||||
opts, args = getopt.gnu_getopt(sys.argv[1:], 'ahrvW:', \
|
||||
['all',
|
||||
'backend=',
|
||||
'force-autoconf',
|
||||
'help',
|
||||
'no-autoconf',
|
||||
'no-patchlist',
|
||||
'version'])
|
||||
except getopt.GetoptError as err:
|
||||
print str(err)
|
||||
sys.exit(2)
|
||||
@ -94,12 +210,19 @@ def main():
|
||||
if o == '-h' or o == '--help':
|
||||
usage()
|
||||
sys.exit(0)
|
||||
elif o == '-v' or o == '--version':
|
||||
with open(stagingdir + 'staging/VERSION') as f:
|
||||
print f.read().rstrip()
|
||||
print 'wine-staging is distributed under the GNU LGPL 2.1.'
|
||||
print 'See individual files for copyright information.'
|
||||
sys.exit(0)
|
||||
elif o == '-r' or o == '--rebase-mode':
|
||||
no_autoconf = True
|
||||
no_patchlist = True
|
||||
backend = "git-am-C1"
|
||||
elif o == '-W':
|
||||
elif o == '-W' or o == '--exclude':
|
||||
excluded.append(a)
|
||||
elif o == '--all':
|
||||
elif o == '-a' or o == '--all':
|
||||
for name in os.listdir(patchdir):
|
||||
path = patchdir + '/' + name
|
||||
if os.path.isdir(path):
|
||||
@ -110,13 +233,17 @@ def main():
|
||||
backend = a
|
||||
elif o == '--no-autoconf':
|
||||
no_autoconf = True
|
||||
elif o == '--force-autoconf':
|
||||
force_autoconf = True
|
||||
elif o == '--no-patchlist':
|
||||
no_patchlist = True
|
||||
|
||||
for a in args: add_patchset(patchlist, a)
|
||||
|
||||
for p in excluded: del patchlist[p]
|
||||
|
||||
if not patchlist:
|
||||
print 'Error: no patches specified'
|
||||
print 'No patches specified, either use -a or specify one or more patch sets as arguments.'
|
||||
sys.exit(1)
|
||||
|
||||
# Check that all of our dependencies exist
|
||||
@ -133,12 +260,12 @@ def main():
|
||||
if not apply_set(patchlist, p):
|
||||
sys.exit(1)
|
||||
|
||||
# we successfully applied everything, autogen some files so we can build
|
||||
if not no_autoconf:
|
||||
print 'Calling autoreconf -f...'
|
||||
subprocess.call(['autoreconf','-f'],cwd=winedir)
|
||||
print 'Calling tools/make_requests...'
|
||||
subprocess.call(['./tools/make_requests'],cwd=winedir)
|
||||
if 'Staging' in patchlist and not no_patchlist:
|
||||
generate_patchlist(patchlist)
|
||||
|
||||
if not no_autoconf and not force_autoconf:
|
||||
run(['autoreconf','-f'],cwd=winedir)
|
||||
run(['./tools/make_requests'],cwd=winedir)
|
||||
sys.exit(0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
Loading…
Reference in New Issue
Block a user