/
mag.py
executable file
·124 lines (115 loc) · 4.83 KB
/
mag.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#!/usr/bin/env python
# Delver Archive patcher / patch maker for the Host System. Should be a useful
# example of how to use delv.archive.Patch
#
# Copyright 2015 Bryce Schroeder, www.bryce.pw, bryce.schroeder@gmail.com
# Wiki: http://www.ferazelhosting.net/wiki/mag.py
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Please do not make trouble for me or the Technical Documentation Project by
# using this software to create versions of the "Cythera Data" file which
# have bypassed registration checks.
# Also, remember that the "Cythera Data" file is copyrighted by Ambrosia and
# /or Glenn Andreas, and publishing modified versions without their permission
# would violate that copyright.
#
# "Cythera" and "Delver" are trademarks of either Glenn Andreas or
# Ambrosia Software, Inc.
from __future__ import absolute_import, division, print_function, unicode_literals
MAGPY_HELP = """
mag.py [COMMAND [arguments...]]
Program for creating and using Delver Archive patches.
Any "FILE" mentioned below can also be a directory.
Available Commands:
patch BASE-FILE PATCH-FILE1 [... PATCH-FILEN] RESULT-FILE
Apply a patch named PATCH-FILE to BASE-FILE, and
save the result to RESULT-FILE. Note that BASE-FILE is not modified.
diff BASE-FILE NEW-FILE RESULT-FILE [INFO-FILE]
Create a patch that will modify BASE-FILE to be the same as NEW-FILE
when it is applied, saving the new patch in RESULT-FILE. If INFO-FILE
is supplied, it stores that in the new patch.
info PATCH-FILE
Print the description of the patch from its patch resource (0xFFFF)
compatible PATCH1 PATCH2 [... PATCHN]
Report if the listed patches are compatible, i.e. if they overwrite
none of the same resources (0xFFFF excepted.)
If no command is given, mag.py with launch in GUI mode, if available.
Note that the patches mag.py creates are not compatible with Magpie. mag.py
is however compatible with Magpie patches and can apply them. Also note that
unlike Magpie, mag.py is not a patch manager; it only creates and applies
patches. It can't unapply them.
"""
import delv
DEFAULT_INFO = "Created with mag.py, http://www.ferazelhosting.net/wiki/mag.py"
SIGNATURE = "Made with delv %s"%delv.version
import delv.archive
from sys import argv,exit,stderr
import os
import textwrap
import itertools
if len(argv) < 2:
# GUI mode
print("GUI not implemented yet; use CLI mode", file=stderr)
print(MAGPY_HELP, file=stderr)
exit(-1)
command = argv[1]
if command == 'info':
patcharch = delv.archive.Patch(argv[2])
print(" ----- PATCH INFO FOR '%s' ----- "%os.path.basename(argv[2]))
pinfo = patcharch.get_patch_info()
if not pinfo:
print("This doesn't appear to contain a patch resource (0xFFFF);")
print("It's probably not a patch.")
else: # Print it out nicely formatted to the terminal width
print(textwrap.fill(str(pinfo),79))
elif command == 'compatible':
combos = itertools.combinations(
[(delv.archive.Patch(path),
os.path.basename(path)) for path in argv[2:]], 2)
conflicts = False
for (a,aname),(b,bname) in combos:
if not a.compatible(b):
print(aname, "conflicts with", bname)
conflicts = True
break
if conflicts:
print("This combination of patches may result in undefined behavior.")
exit(-3)
else:
print("This combination of patches seems to be compatible.")
print("(Of course, this is not certain to be the case.)")
exit(0)
elif command == 'diff':
info = open(argv[5]).read() if len(argv)>5 else DEFAULT_INFO
newpatch = delv.archive.Patch()
newpatch.patch_info(info)
destination = argv[4]
base = delv.archive.Scenario(argv[2])
newversion = delv.archive.Scenario(argv[3])
newpatch.diff(base, newversion)
print("New patch will modify %d resources."%len(newpatch.resources()))
newpatch.to_path(destination)
elif command == 'patch':
base = delv.archive.Scenario(argv[2])
patches = [delv.archive.Patch(path) for path in argv[3:-1]]
destination = argv[-1]
for patch in patches:
patch.patch(base)
print("Applied.")
base.to_path(destination)
else:
print("Unrecognized command", command, file=stderr)
print(MAGPY_HELP, file=stderr)
exit(-2)