diff --git a/staging/patchinstall.py b/staging/patchinstall.py new file mode 100755 index 00000000..ed7ea236 --- /dev/null +++ b/staging/patchinstall.py @@ -0,0 +1,145 @@ +#!/usr/bin/env python2 + +import getopt, os, subprocess, sys + +patchdir = os.path.dirname(os.path.realpath(__file__)) + '/../patches/' +if 'DESTDIR' in os.environ: + winedir = os.environ['DESTDIR'] +else: + winedir = '.' +backend = "patch" + +applied = [] + +def usage(): + print ''' +Usage: ./staging/patchinstall.py [DESTDIR=path] [options] [patchset ...] + +Applies every patch to a Wine tree. + +Options: + -h, --help print this message + --all apply all patches (except those excluded with -W) + -W exclude a patch + --no-autoconf do not run autoconf and tools/make_requests + --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 +''' + +# 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(): + if l.lower().startswith('depends: '): + deps.append(l.split(' ')[1].strip()) + elif l.lower().strip() == 'disabled: true': + return None + return deps + +def apply_patch(patch): + if backend == 'git-am': + return subprocess.call(['git','-C',winedir,'am',patch]) + elif backend == 'git-am-C1': + return subprocess.call(['git','-C',winedir,'am','-C1',patch]) + elif backend == 'patch': + with open(patch) as f: + return subprocess.call([patchdir+'/gitapply.sh'],stdin=f) + elif backend == 'git-apply': + return subprocess.call(['git','-C',winedir,'apply','--index',patch]) + +def apply_set(patchlist, name): + if name in applied: + return True + 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 + applied.append(name) + return True + +def add_patchset(patchlist, name): + path = patchdir + '/' + name + if os.path.isdir(path): + deps = parse_def_file(name, path + '/definition') + if deps == None: + print 'Error: attempt to apply %s, but it is disabled.' %name + sys.exit(1) + patchlist[name] = deps + for dep in deps: add_patchset(patchlist, dep) + +def main(): + global backend + patchlist = {} + excluded = [] + no_autoconf = False + force_autoconf = False + + try: + opts, args = getopt.getopt(sys.argv[1:], 'hrW:', ['all', 'backend', 'help', 'no-autoconf']) + except getopt.GetoptError as err: + print str(err) + sys.exit(2) + + for o, a in opts: + if o == '-h' or o == '--help': + usage() + sys.exit(0) + elif o == '-r' or o == '--rebase-mode': + no_autoconf = True + backend = "git-am-C1" + elif o == '-W': + excluded.append(a) + elif o == '--all': + for name in os.listdir(patchdir): + path = patchdir + '/' + name + if os.path.isdir(path): + deps = parse_def_file(name, path + '/definition') + if deps != None: # it's not disabled + patchlist[name] = deps + elif o == '--backend': + backend = a + elif o == '--no-autoconf': + no_autoconf = True + + for a in args: add_patchset(patchlist, a) + + for p in excluded: del patchlist[p] + + if not patchlist: + print 'Error: no patches specified' + sys.exit(1) + + # Check that all of our dependencies exist + for p in patchlist: + deps = patchlist[p] + for d in deps: + if d not in patchlist: + print 'Error: unknown or disabled dependency %s of %s.' %(d,p) + sys.exit(1) + + # Now try to apply each patch + for p in sorted(patchlist.keys()): + # Try to apply it + 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) + sys.exit(0) + +if __name__ == '__main__': + main()