0.1.1
by Michael Ellerman
Initial import |
1 |
#!/usr/bin/python
|
2 |
||
0.1.6
by Michael Ellerman
Move selection code into HunkSelector class |
3 |
from patches import parse_patches |
0.1.1
by Michael Ellerman
Initial import |
4 |
import os |
5 |
import sys |
|
6 |
import string |
|
0.1.23
by Michael Ellerman
Incorporate Aaron's changes from bzrtools. |
7 |
import glob |
8 |
import bzrlib |
|
9 |
from bzrlib.commands import Command |
|
10 |
from bzrlib.branch import Branch |
|
11 |
from bzrlib import DEFAULT_IGNORE |
|
12 |
from hunk_selector import HunkSelector |
|
0.1.35
by Michael Ellerman
Use DiffStat rather than calling out to /bin/diffstat |
13 |
from diffstat import DiffStat |
0.1.23
by Michael Ellerman
Incorporate Aaron's changes from bzrtools. |
14 |
|
15 |
DEFAULT_IGNORE.append('./.bzr-shelf*') |
|
0.1.1
by Michael Ellerman
Initial import |
16 |
|
0.1.27
by Michael Ellerman
Move all shelf functions into a class. Only logic change is we save the |
17 |
class QuitException(Exception): |
18 |
pass
|
|
19 |
||
20 |
class Shelf(object): |
|
0.1.43
by Michael Ellerman
New shelf layout. Shelves now sit under .bzr/x-shelf/default/ |
21 |
def __init__(self, location, name='default'): |
0.1.38
by Michael Ellerman
Shelf() takes a location which specifies where to open the branch. |
22 |
self.branch = Branch.open_containing(location)[0] |
0.1.43
by Michael Ellerman
New shelf layout. Shelves now sit under .bzr/x-shelf/default/ |
23 |
base = self.branch.controlfilename('x-shelf') |
24 |
self.shelf_dir = os.path.join(base, name) |
|
25 |
||
26 |
# FIXME surely there's an easier way to do this?
|
|
27 |
t = self.branch._transport |
|
28 |
for dir in [base, self.shelf_dir]: |
|
29 |
if not t.has(dir): |
|
30 |
t.mkdir(dir) |
|
31 |
||
32 |
def __path(self, idx): |
|
33 |
return os.path.join(self.shelf_dir, '%.2d' % idx) |
|
0.1.27
by Michael Ellerman
Move all shelf functions into a class. Only logic change is we save the |
34 |
|
35 |
def next_shelf(self): |
|
0.1.43
by Michael Ellerman
New shelf layout. Shelves now sit under .bzr/x-shelf/default/ |
36 |
index = 0 |
37 |
while True: |
|
38 |
name = self.__path(index) |
|
0.1.27
by Michael Ellerman
Move all shelf functions into a class. Only logic change is we save the |
39 |
if not os.path.exists(name): |
40 |
return name |
|
0.1.43
by Michael Ellerman
New shelf layout. Shelves now sit under .bzr/x-shelf/default/ |
41 |
index += 1 |
0.1.27
by Michael Ellerman
Move all shelf functions into a class. Only logic change is we save the |
42 |
|
43 |
def last_shelf(self): |
|
0.1.43
by Michael Ellerman
New shelf layout. Shelves now sit under .bzr/x-shelf/default/ |
44 |
shelves = os.listdir(self.shelf_dir) |
45 |
indexes = [int(f) for f in shelves] |
|
46 |
indexes.sort() |
|
0.1.27
by Michael Ellerman
Move all shelf functions into a class. Only logic change is we save the |
47 |
|
0.1.43
by Michael Ellerman
New shelf layout. Shelves now sit under .bzr/x-shelf/default/ |
48 |
if len(indexes) == 0: |
0.1.27
by Michael Ellerman
Move all shelf functions into a class. Only logic change is we save the |
49 |
return None |
0.1.43
by Michael Ellerman
New shelf layout. Shelves now sit under .bzr/x-shelf/default/ |
50 |
|
51 |
return self.__path(indexes[-1]) |
|
0.1.27
by Michael Ellerman
Move all shelf functions into a class. Only logic change is we save the |
52 |
|
53 |
def get_shelf_message(self, shelf): |
|
54 |
prefix = "# shelf: " |
|
55 |
if not shelf.startswith(prefix): |
|
56 |
return None |
|
57 |
return shelf[len(prefix):shelf.index('\n')] |
|
58 |
||
0.1.55
by Michael Ellerman
Add support for 'unshelve --pick'. This works but the UI is broken, as the |
59 |
def unshelve(self, pick_hunks=False): |
0.1.27
by Michael Ellerman
Move all shelf functions into a class. Only logic change is we save the |
60 |
shelf = self.last_shelf() |
61 |
||
62 |
if shelf is None: |
|
0.1.31
by Michael Ellerman
- Keep our branch around, and use it directly instead of bzr_root. |
63 |
raise Exception("No shelf found in '%s'" % self.branch.base) |
0.1.27
by Michael Ellerman
Move all shelf functions into a class. Only logic change is we save the |
64 |
|
0.1.55
by Michael Ellerman
Add support for 'unshelve --pick'. This works but the UI is broken, as the |
65 |
patches = parse_patches(open(shelf, 'r').readlines()) |
66 |
if pick_hunks: |
|
67 |
try: |
|
68 |
patches = HunkSelector(patches).select() |
|
69 |
except QuitException: |
|
70 |
return False |
|
71 |
||
72 |
if len(patches) == 0: |
|
73 |
print >>sys.stderr, 'Nothing to unshelve' |
|
74 |
return True |
|
0.1.27
by Michael Ellerman
Move all shelf functions into a class. Only logic change is we save the |
75 |
|
76 |
print >>sys.stderr, "Reapplying shelved patches", |
|
0.1.55
by Michael Ellerman
Add support for 'unshelve --pick'. This works but the UI is broken, as the |
77 |
message = self.get_shelf_message(open(shelf, 'r').read()) |
0.1.27
by Michael Ellerman
Move all shelf functions into a class. Only logic change is we save the |
78 |
if message is not None: |
79 |
print >>sys.stderr, ' "%s"' % message |
|
80 |
else: |
|
81 |
print >>sys.stderr, "" |
|
0.1.31
by Michael Ellerman
- Keep our branch around, and use it directly instead of bzr_root. |
82 |
pipe = os.popen('patch -d %s -s -p0' % self.branch.base, 'w') |
0.1.55
by Michael Ellerman
Add support for 'unshelve --pick'. This works but the UI is broken, as the |
83 |
for patch in patches: |
84 |
pipe.write(str(patch)) |
|
0.1.27
by Michael Ellerman
Move all shelf functions into a class. Only logic change is we save the |
85 |
pipe.flush() |
86 |
||
87 |
if pipe.close() is not None: |
|
88 |
raise Exception("Failed running patch!") |
|
89 |
||
90 |
os.remove(shelf) |
|
0.1.35
by Michael Ellerman
Use DiffStat rather than calling out to /bin/diffstat |
91 |
|
92 |
diff_stat = DiffStat(self.get_patches(None, None)) |
|
93 |
print 'Diff status is now:\n', diff_stat |
|
0.1.27
by Michael Ellerman
Move all shelf functions into a class. Only logic change is we save the |
94 |
|
95 |
return True |
|
96 |
||
0.1.31
by Michael Ellerman
- Keep our branch around, and use it directly instead of bzr_root. |
97 |
def get_patches(self, revision, file_list): |
98 |
from StringIO import StringIO |
|
99 |
from bzrlib.diff import show_diff |
|
100 |
out = StringIO() |
|
101 |
show_diff(self.branch, revision, specific_files=file_list, output=out) |
|
102 |
out.seek(0) |
|
103 |
return out.readlines() |
|
104 |
||
0.1.46
by Michael Ellerman
Shelve everything by default, use --pick to select hunks individually. |
105 |
def shelve(self, pick_hunks=False, message=None, revision=None, |
0.1.28
by Michael Ellerman
Implement "bzr shelve --all". |
106 |
file_list=None): |
0.1.31
by Michael Ellerman
- Keep our branch around, and use it directly instead of bzr_root. |
107 |
patches = parse_patches(self.get_patches(revision, file_list)) |
108 |
||
0.1.46
by Michael Ellerman
Shelve everything by default, use --pick to select hunks individually. |
109 |
if pick_hunks: |
0.1.28
by Michael Ellerman
Implement "bzr shelve --all". |
110 |
try: |
111 |
patches = HunkSelector(patches).select() |
|
112 |
except QuitException: |
|
113 |
return False |
|
0.1.27
by Michael Ellerman
Move all shelf functions into a class. Only logic change is we save the |
114 |
|
115 |
if len(patches) == 0: |
|
116 |
print >>sys.stderr, 'Nothing to shelve' |
|
117 |
return True |
|
118 |
||
119 |
shelf = self.next_shelf() |
|
120 |
print >>sys.stderr, "Saving shelved patches to", shelf |
|
121 |
shelf = open(shelf, 'a') |
|
122 |
if message is not None: |
|
123 |
assert '\n' not in message |
|
124 |
shelf.write("# shelf: %s\n" % message) |
|
125 |
for patch in patches: |
|
126 |
shelf.write(str(patch)) |
|
127 |
||
128 |
shelf.flush() |
|
129 |
os.fsync(shelf.fileno()) |
|
130 |
shelf.close() |
|
131 |
||
132 |
print >>sys.stderr, "Reverting shelved patches" |
|
0.1.31
by Michael Ellerman
- Keep our branch around, and use it directly instead of bzr_root. |
133 |
pipe = os.popen('patch -d %s -sR -p0' % self.branch.base, 'w') |
0.1.27
by Michael Ellerman
Move all shelf functions into a class. Only logic change is we save the |
134 |
for patch in patches: |
135 |
pipe.write(str(patch)) |
|
136 |
pipe.flush() |
|
137 |
||
138 |
if pipe.close() is not None: |
|
139 |
raise Exception("Failed running patch!") |
|
140 |
||
0.1.35
by Michael Ellerman
Use DiffStat rather than calling out to /bin/diffstat |
141 |
diff_stat = DiffStat(self.get_patches(None, None)) |
142 |
print 'Diff status is now:\n', diff_stat |
|
0.1.27
by Michael Ellerman
Move all shelf functions into a class. Only logic change is we save the |
143 |
|
144 |
return True |
|
145 |