~abentley/bzrtools/bzrtools.dev

« back to all changes in this revision

Viewing changes to shelf.py

  • Committer: Michael Ellerman
  • Date: 2005-10-19 11:34:39 UTC
  • mto: (0.3.1 shelf-dev) (325.1.2 bzrtools)
  • mto: This revision was merged to the branch mainline in revision 246.
  • Revision ID: michael@ellerman.id.au-20051019113439-193bca379eec5798
Move all shelf functions into a class. Only logic change is we save the
bzr root dir rather than recomputing it again and again.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/python
 
2
 
 
3
from patches import parse_patches
 
4
import os
 
5
import sys
 
6
import string
 
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
 
13
 
 
14
DEFAULT_IGNORE.append('./.bzr-shelf*')
 
15
 
 
16
def run_bzr(args):
 
17
    if type(args) is str:
 
18
        args = [ args ]
 
19
    pipe = os.popen('bzr %s' % string.join(args, ' '), 'r')
 
20
    lines = pipe.readlines()
 
21
    if pipe.close() is not None:
 
22
        raise Exception("Failed running bzr")
 
23
    return lines
 
24
 
 
25
class QuitException(Exception):
 
26
    pass
 
27
 
 
28
class Shelf(object):
 
29
    def __init__(self):
 
30
        self.bzr_root = run_bzr('root')[0].strip()
 
31
 
 
32
    def shelf_suffix(self, index):
 
33
        if index == 0:
 
34
            return ""
 
35
        else:
 
36
            return "-%d" % index
 
37
 
 
38
    def next_shelf(self):
 
39
        def name_sequence():
 
40
            i = 0
 
41
            while True:
 
42
                yield self.shelf_suffix(i)
 
43
                i = i + 1
 
44
 
 
45
        stem = os.path.join(self.bzr_root, '.bzr-shelf')
 
46
        for end in name_sequence():
 
47
            name = stem + end
 
48
            if not os.path.exists(name):
 
49
                return name
 
50
 
 
51
    def last_shelf(self):
 
52
        stem = os.path.join(self.bzr_root, '.bzr-shelf')
 
53
        shelves = glob.glob(stem)
 
54
        shelves.extend(glob.glob(stem + '-*'))
 
55
        def shelf_index(name):
 
56
            if name == stem:
 
57
                return 0
 
58
            return int(name[len(stem)+1:])
 
59
        shelvenums = [shelf_index(f) for f in shelves]
 
60
        shelvenums.sort()
 
61
 
 
62
        if len(shelvenums) == 0:
 
63
            return None
 
64
        return stem + self.shelf_suffix(shelvenums[-1])
 
65
 
 
66
    def get_shelf_message(self, shelf):
 
67
        prefix = "# shelf: "
 
68
        if not shelf.startswith(prefix):
 
69
            return None
 
70
        return shelf[len(prefix):shelf.index('\n')]
 
71
 
 
72
    def unshelve(self):
 
73
        shelf = self.last_shelf()
 
74
 
 
75
        if shelf is None:
 
76
            raise Exception("No shelf found in '%s'" % self.bzr_root)
 
77
 
 
78
        patch = open(shelf, 'r').read()
 
79
 
 
80
        print >>sys.stderr, "Reapplying shelved patches",
 
81
        message = self.get_shelf_message(patch)
 
82
        if message is not None:
 
83
            print >>sys.stderr, ' "%s"' % message
 
84
        else:
 
85
            print >>sys.stderr, ""
 
86
        pipe = os.popen('patch -d %s -s -p0' % self.bzr_root, 'w')
 
87
        pipe.write(patch)
 
88
        pipe.flush()
 
89
 
 
90
        if pipe.close() is not None:
 
91
            raise Exception("Failed running patch!")
 
92
 
 
93
        os.remove(shelf)
 
94
        print 'Diff status is now:'
 
95
        os.system('bzr diff | diffstat')
 
96
 
 
97
        return True
 
98
 
 
99
    def shelve(self, message=None, revision=None, file_list=None):
 
100
        cmd = ['diff']
 
101
        if revision is not None:
 
102
            cmd.extend(['--revision', str(revision[0])])
 
103
        if file_list is not None:
 
104
            cmd.extend(file_list)
 
105
        patches = parse_patches(run_bzr(cmd))
 
106
        try:
 
107
            patches = HunkSelector(patches).select()
 
108
        except QuitException:
 
109
            return False
 
110
 
 
111
        if len(patches) == 0:
 
112
            print >>sys.stderr, 'Nothing to shelve'
 
113
            return True
 
114
 
 
115
        shelf = self.next_shelf()
 
116
        print >>sys.stderr, "Saving shelved patches to", shelf
 
117
        shelf = open(shelf, 'a')
 
118
        if message is not None:
 
119
            assert '\n' not in message
 
120
            shelf.write("# shelf: %s\n" % message)
 
121
        for patch in patches:
 
122
            shelf.write(str(patch))
 
123
 
 
124
        shelf.flush()
 
125
        os.fsync(shelf.fileno())
 
126
        shelf.close()
 
127
 
 
128
        print >>sys.stderr, "Reverting shelved patches"
 
129
        pipe = os.popen('patch -d %s -sR -p0' % self.bzr_root, 'w')
 
130
        for patch in patches:
 
131
            pipe.write(str(patch))
 
132
        pipe.flush()
 
133
 
 
134
        if pipe.close() is not None:
 
135
            raise Exception("Failed running patch!")
 
136
 
 
137
        print 'Diff status is now:'
 
138
        os.system('bzr diff | diffstat')
 
139
 
 
140
        return True
 
141