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
125
126
127
128
|
#!/usr/bin/python
import os
import sys
from errors import CommandError
from hunk_selector import ShelveHunkSelector, UnshelveHunkSelector
from diffstat import DiffStat
from patchsource import PatchSource, FilePatchSource
BASE_DIR = '.shelf'
class Shelf(object):
def __init__(self, base, name='default'):
self.base = base
shelf_base = os.path.join(self.base, BASE_DIR)
self.shelf_dir = os.path.join(shelf_base, name)
for dir in [shelf_base, self.shelf_dir]:
if not os.path.isdir(dir):
os.mkdir(dir)
def __path(self, idx):
return os.path.join(self.shelf_dir, '%.2d' % idx)
def next_shelf(self):
index = 0
while True:
name = self.__path(index)
if not os.path.exists(name):
return name
index += 1
def last_shelf(self):
shelves = os.listdir(self.shelf_dir)
indexes = [int(f) for f in shelves]
indexes.sort()
if len(indexes) == 0:
return None
return self.__path(indexes[-1])
def get_shelf_message(self, shelf):
prefix = "# shelf: "
if not shelf.startswith(prefix):
return None
return shelf[len(prefix):shelf.index('\n')]
def __show_status(self, source):
if source.can_live_update():
diff_stat = DiffStat(source.readlines())
print 'Diff status is now:\n', diff_stat
def unshelve(self, patch_source, pick_hunks=False):
shelf = self.last_shelf()
if shelf is None:
raise CommandError("No shelf found in '%s'" % self.base)
patches = FilePatchSource(shelf).readpatches()
if pick_hunks:
to_unshelve, to_remain = UnshelveHunkSelector(patches).select()
else:
to_unshelve = patches
to_remain = []
if len(to_unshelve) == 0:
raise CommandError('Nothing to unshelve')
print >>sys.stderr, "Reapplying shelved patches",
message = self.get_shelf_message(open(shelf, 'r').read())
if message is not None:
print >>sys.stderr, ' "%s"' % message
else:
print >>sys.stderr, ""
pipe = os.popen('patch -d %s -s -p0' % self.base, 'w')
for patch in to_unshelve:
pipe.write(str(patch))
pipe.flush()
if pipe.close() is not None:
raise CommandError("Failed running patch!")
if len(to_remain) == 0:
os.remove(shelf)
else:
f = open(shelf, 'w')
for patch in to_remain:
f.write(str(patch))
f.close()
self.__show_status(patch_source)
def shelve(self, patch_source, pick_hunks=False, message=None):
patches = patch_source.readpatches()
if pick_hunks:
to_shelve = ShelveHunkSelector(patches).select()[0]
else:
to_shelve = patches
if len(to_shelve) == 0:
raise CommandError('Nothing to shelve')
shelf = self.next_shelf()
print >>sys.stderr, "Saving shelved patches to", shelf
shelf = open(shelf, 'a')
if message is not None:
assert '\n' not in message
shelf.write("# shelf: %s\n" % message)
for patch in to_shelve:
shelf.write(str(patch))
shelf.flush()
os.fsync(shelf.fileno())
shelf.close()
print >>sys.stderr, "Reverting shelved patches"
pipe = os.popen('patch -d %s -sR -p0' % self.base, 'w')
for patch in to_shelve:
pipe.write(str(patch))
pipe.flush()
if pipe.close() is not None:
raise CommandError("Failed running patch!")
self.__show_status(patch_source)
|