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
129
130
131
132
133
|
#!/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.name = name
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 = str(DiffStat(source.readlines()))
if len(diff_stat) > 0:
print >> sys.stderr, 'Diff status is now:\n', diff_stat
else:
print >> sys.stderr, 'No changes left in working tree.'
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 to shelf '%s', patch '%s'" % \
(self.name, os.path.basename(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)
|