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
134
135
136
137
138
139
140
|
#!/usr/bin/python
from patches import parse_patches
import os
import sys
from bzrlib.commands import Command
from bzrlib.branch import Branch
from bzrlib import DEFAULT_IGNORE
from bzrlib.errors import BzrCommandError
from hunk_selector import ShelveHunkSelector, UnshelveHunkSelector
from diffstat import DiffStat
DEFAULT_IGNORE.append('./.bzr-shelf*')
class Shelf(object):
def __init__(self, location, name='default'):
self.branch = Branch.open_containing(location)[0]
base = self.branch.controlfilename('x-shelf')
self.shelf_dir = os.path.join(base, name)
# FIXME surely there's an easier way to do this?
t = self.branch._transport
for dir in [base, self.shelf_dir]:
if not t.has(dir):
t.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 unshelve(self, pick_hunks=False):
shelf = self.last_shelf()
if shelf is None:
raise BzrCommandError("No shelf found in branch '%s'" % \
self.branch.base)
patches = parse_patches(open(shelf, 'r').readlines())
if pick_hunks:
to_unshelve, to_remain = UnshelveHunkSelector(patches).select()
else:
to_unshelve = patches
to_remain = []
if len(to_unshelve) == 0:
raise BzrCommandError('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.branch.base, 'w')
for patch in to_unshelve:
pipe.write(str(patch))
pipe.flush()
if pipe.close() is not None:
raise BzrCommandError("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()
diff_stat = DiffStat(self.get_patches(None, None))
print 'Diff status is now:\n', diff_stat
def get_patches(self, revision, file_list):
from StringIO import StringIO
from bzrlib.diff import show_diff
out = StringIO()
show_diff(self.branch, revision, specific_files=file_list, output=out)
out.seek(0)
return out.readlines()
def shelve(self, pick_hunks=False, message=None, revision=None,
file_list=None):
patches = parse_patches(self.get_patches(revision, file_list))
if pick_hunks:
to_shelve = ShelveHunkSelector(patches).select()[0]
else:
to_shelve = patches
if len(to_shelve) == 0:
raise BzrCommandError('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.branch.base, 'w')
for patch in to_shelve:
pipe.write(str(patch))
pipe.flush()
if pipe.close() is not None:
raise BzrCommandError("Failed running patch!")
diff_stat = DiffStat(self.get_patches(None, None))
print 'Diff status is now:\n', diff_stat
|