3
from patches import parse_patches
9
from bzrlib.commands import Command
10
from bzrlib.branch import Branch
11
from bzrlib import DEFAULT_IGNORE
12
from hunk_selector import HunkSelector
5
from errors import CommandError
6
from hunk_selector import ShelveHunkSelector, UnshelveHunkSelector
13
7
from diffstat import DiffStat
15
DEFAULT_IGNORE.append('./.bzr-shelf*')
17
class QuitException(Exception):
8
from patchsource import PatchSource, FilePatchSource
20
12
class Shelf(object):
21
def __init__(self, location):
22
self.branch = Branch.open_containing(location)[0]
24
def shelf_suffix(self, index):
13
def __init__(self, base, name='default'):
16
shelf_base = os.path.join(self.base, BASE_DIR)
17
self.shelf_dir = os.path.join(shelf_base, name)
19
for dir in [shelf_base, self.shelf_dir]:
20
if not os.path.isdir(dir):
23
def __path(self, idx):
24
return os.path.join(self.shelf_dir, '%.2d' % idx)
30
26
def next_shelf(self):
34
yield self.shelf_suffix(i)
37
stem = os.path.join(self.branch.base, '.bzr-shelf')
38
for end in name_sequence():
29
name = self.__path(index)
40
30
if not os.path.exists(name):
43
34
def last_shelf(self):
44
stem = os.path.join(self.branch.base, '.bzr-shelf')
45
shelves = glob.glob(stem)
46
shelves.extend(glob.glob(stem + '-*'))
47
def shelf_index(name):
50
return int(name[len(stem)+1:])
51
shelvenums = [shelf_index(f) for f in shelves]
35
shelves = os.listdir(self.shelf_dir)
36
indexes = [int(f) for f in shelves]
54
if len(shelvenums) == 0:
56
return stem + self.shelf_suffix(shelvenums[-1])
42
return self.__path(indexes[-1])
58
44
def get_shelf_message(self, shelf):
59
45
prefix = "# shelf: "
62
48
return shelf[len(prefix):shelf.index('\n')]
50
def __show_status(self, source):
51
if source.can_live_update():
52
diff_stat = str(DiffStat(source.readlines()))
53
if len(diff_stat) > 0:
54
print >> sys.stderr, 'Diff status is now:\n', diff_stat
56
print >> sys.stderr, 'No changes left in working tree.'
58
def unshelve(self, patch_source, pick_hunks=False):
65
59
shelf = self.last_shelf()
68
raise Exception("No shelf found in '%s'" % self.branch.base)
70
patch = open(shelf, 'r').read()
62
raise CommandError("No shelf found in '%s'" % self.base)
64
patches = FilePatchSource(shelf).readpatches()
66
to_unshelve, to_remain = UnshelveHunkSelector(patches).select()
71
if len(to_unshelve) == 0:
72
raise CommandError('Nothing to unshelve')
72
74
print >>sys.stderr, "Reapplying shelved patches",
73
message = self.get_shelf_message(patch)
75
message = self.get_shelf_message(open(shelf, 'r').read())
74
76
if message is not None:
75
77
print >>sys.stderr, ' "%s"' % message
77
79
print >>sys.stderr, ""
78
pipe = os.popen('patch -d %s -s -p0' % self.branch.base, 'w')
81
pipe = os.popen('patch -d %s -s -p0' % self.base, 'w')
82
for patch in to_unshelve:
83
pipe.write(str(patch))
82
86
if pipe.close() is not None:
83
raise Exception("Failed running patch!")
87
diff_stat = DiffStat(self.get_patches(None, None))
88
print 'Diff status is now:\n', diff_stat
92
def get_patches(self, revision, file_list):
93
from StringIO import StringIO
94
from bzrlib.diff import show_diff
96
show_diff(self.branch, revision, specific_files=file_list, output=out)
98
return out.readlines()
100
def shelve(self, all_hunks=False, message=None, revision=None,
102
patches = parse_patches(self.get_patches(revision, file_list))
106
patches = HunkSelector(patches).select()
107
except QuitException:
110
if len(patches) == 0:
111
print >>sys.stderr, 'Nothing to shelve'
87
raise CommandError("Failed running patch!")
89
if len(to_remain) == 0:
93
for patch in to_remain:
97
self.__show_status(patch_source)
99
def shelve(self, patch_source, pick_hunks=False, message=None):
100
patches = patch_source.readpatches()
103
to_shelve = ShelveHunkSelector(patches).select()[0]
107
if len(to_shelve) == 0:
108
raise CommandError('Nothing to shelve')
114
110
shelf = self.next_shelf()
115
print >>sys.stderr, "Saving shelved patches to", shelf
111
print >>sys.stderr, "Saving to shelf '%s', patch '%s'" % \
112
(self.name, os.path.basename(shelf))
116
113
shelf = open(shelf, 'a')
117
114
if message is not None:
118
115
assert '\n' not in message
119
116
shelf.write("# shelf: %s\n" % message)
120
for patch in patches:
117
for patch in to_shelve:
121
118
shelf.write(str(patch))
124
121
os.fsync(shelf.fileno())
127
print >>sys.stderr, "Reverting shelved patches"
128
pipe = os.popen('patch -d %s -sR -p0' % self.branch.base, 'w')
129
for patch in patches:
124
print >>sys.stderr, "Reverting shelved patches."
125
pipe = os.popen('patch -d %s -sR -p0' % self.base, 'w')
126
for patch in to_shelve:
130
127
pipe.write(str(patch))
133
130
if pipe.close() is not None:
134
raise Exception("Failed running patch!")
136
diff_stat = DiffStat(self.get_patches(None, None))
137
print 'Diff status is now:\n', diff_stat
131
raise CommandError("Failed running patch!")
133
self.__show_status(patch_source)