2
2
3
3
import subprocess
4
4
5
- from . import patch
5
+ from . import patch , exceptions
6
6
from .snippets import which , remove
7
7
8
8
@@ -25,62 +25,82 @@ def apply_patch(diffs):
25
25
f .write (new_text )
26
26
27
27
28
+ def _apply_diff_with_subprocess (diff , lines ):
29
+ # call out to patch program
30
+ patchexec = which ('patch' )
31
+ if not patchexec :
32
+ raise exceptions .ApplyException ('patch program does not exist' )
33
+
34
+ filepath = '/tmp/wtp-' + str (hash (diff .header ))
35
+ oldfilepath = filepath + '.old'
36
+ newfilepath = filepath + '.new'
37
+ rejfilepath = filepath + '.rej'
38
+ patchfilepath = filepath + '.patch'
39
+ with open (oldfilepath , 'w' ) as f :
40
+ f .write ('\n ' .join (lines ) + '\n ' )
41
+
42
+ with open (patchfilepath , 'w' ) as f :
43
+ f .write (diff .text )
44
+
45
+ args = [patchexec ,
46
+ '--quiet' ,
47
+ '-o' , newfilepath ,
48
+ '-i' , patchfilepath ,
49
+ '-r' , rejfilepath ,
50
+ oldfilepath
51
+ ]
52
+ ret = subprocess .call (args )
53
+
54
+ with open (newfilepath ) as f :
55
+ lines = f .read ().splitlines ()
56
+
57
+ try :
58
+ with open (rejfilepath ) as f :
59
+ rejlines = f .read ().splitlines ()
60
+ except IOError :
61
+ rejlines = None
62
+
63
+ remove (oldfilepath )
64
+ remove (newfilepath )
65
+ remove (rejfilepath )
66
+ remove (patchfilepath )
67
+
68
+ # do this last to ensure files get cleaned up
69
+ if ret != 0 :
70
+ raise exceptions .ApplyException ('patch program failed' )
71
+
72
+ return lines , rejlines
73
+
74
+
28
75
def apply_diff (diff , text , use_patch = False ):
29
76
try :
30
77
lines = text .splitlines ()
31
78
except AttributeError :
32
79
lines = list (text )
33
80
34
81
if use_patch :
35
- # call out to patch program
36
- patchexec = which ('patch' )
37
- assert patchexec # patch program does not exist
38
-
39
- filepath = '/tmp/wtp-' + str (hash (diff .header ))
40
- oldfilepath = filepath + '.old'
41
- newfilepath = filepath + '.new'
42
- rejfilepath = filepath + '.rej'
43
- patchfilepath = filepath + '.patch'
44
- with open (oldfilepath , 'w' ) as f :
45
- f .write ('\n ' .join (lines ) + '\n ' )
46
-
47
- with open (patchfilepath , 'w' ) as f :
48
- f .write (diff .text )
49
-
50
- args = [patchexec ,
51
- '--quiet' ,
52
- '-o' , newfilepath ,
53
- '-i' , patchfilepath ,
54
- '-r' , rejfilepath ,
55
- oldfilepath
56
- ]
57
- ret = subprocess .call (args )
58
-
59
- with open (newfilepath ) as f :
60
- lines = f .read ().splitlines ()
61
-
62
- try :
63
- with open (rejfilepath ) as f :
64
- rejlines = f .read ().splitlines ()
65
- except IOError :
66
- rejlines = None
67
-
68
- remove (oldfilepath )
69
- remove (newfilepath )
70
- remove (rejfilepath )
71
- remove (patchfilepath )
72
-
73
- # do this last to ensure files get cleaned up
74
- assert ret == 0 # patch return code is success
75
-
76
- return lines , rejlines
82
+ return _apply_diff_with_subprocess (diff , lines )
77
83
84
+ n_lines = len (lines )
78
85
# check that the source text matches the context of the diff
79
86
for old , new , line in diff .changes :
80
87
# might have to check for line is None here for ed scripts
81
88
if old is not None and line is not None :
82
- assert len (lines ) >= old
83
- assert lines [old - 1 ] == line
89
+ if old > n_lines :
90
+ raise exceptions .ApplyException (
91
+ 'context line {n}, "{l}" does not exist in source' .format (
92
+ n = old ,
93
+ l = line ,
94
+ )
95
+ )
96
+ if lines [old - 1 ] != line :
97
+ raise exceptions .ApplyException (
98
+ 'context line {n}, "{l}" does not match "{sl}"' .format (
99
+ n = old ,
100
+ l = line ,
101
+ sl = lines [old - 1 ]
102
+ )
103
+ )
84
104
85
105
# for calculating the old line
86
106
r = 0
0 commit comments