~abentley/bzrtools/bzrtools.dev

« back to all changes in this revision

Viewing changes to bzrtools.py

  • Committer: Aaron Bentley
  • Date: 2005-11-11 17:43:12 UTC
  • Revision ID: aaron.bentley@utoronto.ca-20051111174312-1c627d82a07bf8fd
Added patch for tab-in-patch-filename support

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
#    You should have received a copy of the GNU General Public License
15
15
#    along with this program; if not, write to the Free Software
16
16
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 
import codecs
18
 
import errno
 
17
import bzrlib
 
18
import bzrlib.errors
19
19
import os
20
 
import re
 
20
import os.path
 
21
import sys
21
22
import tempfile
22
23
import shutil
 
24
import errno
23
25
from subprocess import Popen, PIPE
24
 
import sys
25
 
 
26
 
import bzrlib
27
 
import bzrlib.errors
28
 
from bzrlib.errors import BzrCommandError
29
 
from bzrlib.bzrdir import BzrDir
30
 
 
31
 
def temp_tree():
 
26
import codecs
 
27
 
 
28
def temp_branch():
32
29
    dirname = tempfile.mkdtemp("temp-branch")
33
 
    return BzrDir.create_standalone_workingtree(dirname)
34
 
 
35
 
def rm_tree(tree):
36
 
    shutil.rmtree(tree.basedir)
37
 
 
38
 
def is_clean(cur_tree):
 
30
    return bzrlib.branch.Branch.initialize(dirname)
 
31
 
 
32
def rm_branch(br):
 
33
    shutil.rmtree(br.base)
 
34
 
 
35
def is_clean(cur_branch):
39
36
    """
40
37
    Return true if no files are modifed or unknown
41
38
    >>> import bzrlib.add
42
 
    >>> tree = temp_tree()
43
 
    >>> is_clean(tree)
 
39
    >>> br = temp_branch()
 
40
    >>> is_clean(br)
44
41
    (True, [])
45
 
    >>> fooname = os.path.join(tree.basedir, "foo")
 
42
    >>> fooname = os.path.join(br.base, "foo")
46
43
    >>> file(fooname, "wb").write("bar")
47
 
    >>> is_clean(tree)
 
44
    >>> is_clean(br)
48
45
    (True, [u'foo'])
49
 
    >>> bzrlib.add.smart_add_tree(tree, [tree.basedir])
50
 
    ([u'foo'], {})
51
 
    >>> is_clean(tree)
 
46
    >>> bzrlib.add.smart_add_branch(br, [br.base])
 
47
    1
 
48
    >>> is_clean(br)
52
49
    (False, [])
53
 
    >>> tree.commit("added file")
54
 
    >>> is_clean(tree)
 
50
    >>> br.commit("added file")
 
51
    >>> is_clean(br)
55
52
    (True, [])
56
 
    >>> rm_tree(tree)
 
53
    >>> rm_branch(br)
57
54
    """
58
55
    from bzrlib.diff import compare_trees
59
 
    old_tree = cur_tree.basis_tree()
60
 
    new_tree = cur_tree
 
56
    old_tree = cur_branch.basis_tree()
 
57
    new_tree = cur_branch.working_tree()
61
58
    non_source = []
62
59
    for path, file_class, kind, file_id, entry in new_tree.list_files():
63
60
        if file_class in ('?', 'I'):
65
62
    delta = compare_trees(old_tree, new_tree, want_unchanged=False)
66
63
    return not delta.has_changed(), non_source
67
64
 
68
 
def set_push_data(tree, location):
69
 
    push_file = file (tree.branch.control_files.controlfilename("x-push-data"), "wb")
 
65
def set_pull_data(br, location, rev_id):
 
66
    pull_file = file (br.controlfilename("x-pull-data"), "wb")
 
67
    pull_file.write("%s\n%s\n" % (location, rev_id))
 
68
 
 
69
def get_pull_data(br):
 
70
    """
 
71
    >>> br = temp_branch()
 
72
    >>> get_pull_data(br)
 
73
    (None, None)
 
74
    >>> set_pull_data(br, 'http://somewhere', '888-777')
 
75
    >>> get_pull_data(br)
 
76
    ('http://somewhere', '888-777')
 
77
    >>> rm_branch(br)
 
78
    """
 
79
    filename = br.controlfilename("x-pull-data")
 
80
    if not os.path.exists(filename):
 
81
        return (None, None)
 
82
    pull_file = file (filename, "rb")
 
83
    location, rev_id = [f.rstrip('\n') for f in pull_file]
 
84
    return location, rev_id
 
85
 
 
86
def set_push_data(br, location):
 
87
    push_file = file (br.controlfilename("x-push-data"), "wb")
70
88
    push_file.write("%s\n" % location)
71
89
 
72
 
def get_push_data(tree):
 
90
def get_push_data(br):
73
91
    """
74
 
    >>> tree = temp_tree()
75
 
    >>> get_push_data(tree) is None
 
92
    >>> br = temp_branch()
 
93
    >>> get_push_data(br) is None
76
94
    True
77
 
    >>> set_push_data(tree, 'http://somewhere')
78
 
    >>> get_push_data(tree)
 
95
    >>> set_push_data(br, 'http://somewhere')
 
96
    >>> get_push_data(br)
79
97
    'http://somewhere'
80
 
    >>> rm_tree(tree)
 
98
    >>> rm_branch(br)
81
99
    """
82
 
    filename = tree.branch.control_files.controlfilename("x-push-data")
 
100
    filename = br.controlfilename("x-push-data")
83
101
    if not os.path.exists(filename):
84
102
        return None
85
103
    push_file = file (filename, "rb")
115
133
def rsync(source, target, ssh=False, excludes=(), silent=False, 
116
134
          rsync_name="rsync"):
117
135
    """
118
 
    >>> new_dir = tempfile.mkdtemp()
119
 
    >>> old_dir = os.getcwd()
120
 
    >>> os.chdir(new_dir)
121
136
    >>> rsync("a", "b", silent=True)
122
137
    Traceback (most recent call last):
123
 
    RsyncNoFile: No such file...
124
 
    >>> rsync(new_dir + "/a", new_dir + "/b", excludes=("*.py",), silent=True)
 
138
    RsyncNoFile: No such file a
 
139
    >>> rsync("a", "b", excludes=("*.py",), silent=True)
125
140
    Traceback (most recent call last):
126
 
    RsyncNoFile: No such file...
127
 
    >>> rsync(new_dir + "/a", new_dir + "/b", excludes=("*.py",), silent=True, rsync_name="rsyncc")
 
141
    RsyncNoFile: No such file a
 
142
    >>> rsync("a", "b", excludes=("*.py",), silent=True, rsync_name="rsyncc")
128
143
    Traceback (most recent call last):
129
144
    NoRsync: rsyncc not found.
130
 
    >>> os.chdir(old_dir)
131
 
    >>> os.rmdir(new_dir)
132
145
    """
133
146
    cmd = [rsync_name, "-av", "--delete"]
134
147
    if ssh:
189
202
        raise RsyncUnknownStatus(proc.returncode)
190
203
    return [l.split(' ')[-1].rstrip('\n') for l in result.splitlines(True)]
191
204
 
192
 
exclusions = ('.bzr/x-push-data', '.bzr/branch/x-push/data', '.bzr/parent', 
193
 
              '.bzr/branch/parent', '.bzr/x-pull-data', '.bzr/x-pull',
194
 
              '.bzr/pull', '.bzr/stat-cache', '.bzr/x-rsync-data',
195
 
              '.bzr/basis-inventory', '.bzr/inventory.backup.weave')
 
205
exclusions = ('.bzr/x-push-data', '.bzr/parent', '.bzr/x-pull-data', 
 
206
              '.bzr/x-pull', '.bzr/pull', '.bzr/stat-cache',
 
207
              '.bzr/x-rsync-data')
196
208
 
197
209
 
198
210
def read_revision_history(fname):
211
223
    tempdir = tempfile.mkdtemp('push')
212
224
    try:
213
225
        history_fname = os.path.join(tempdir, 'revision-history')
214
 
        try:
215
 
            cmd = rsync(location+'.bzr/revision-history', history_fname,
216
 
                        silent=True)
217
 
        except RsyncNoFile:
218
 
            cmd = rsync(location+'.bzr/branch/revision-history', history_fname,
219
 
                        silent=True)
 
226
        cmd = rsync(location+'.bzr/revision-history', history_fname,
 
227
                    silent=True)
220
228
        history = read_revision_history(history_fname)
221
229
    finally:
222
230
        shutil.rmtree(tempdir)
239
247
    except RsyncNoFile:
240
248
        return True
241
249
 
242
 
def push(tree, location=None, overwrite=False, working_tree=True):
243
 
    push_location = get_push_data(tree)
 
250
def push(cur_branch, location=None, overwrite=False):
 
251
    push_location = get_push_data(cur_branch)
244
252
    if location is not None:
245
253
        if not location.endswith('/'):
246
254
            location += '/'
247
255
        push_location = location
248
256
    
249
257
    if push_location is None:
250
 
        if tree.branch.get_push_location() is None:
251
 
            raise BzrCommandError("No push location known or specified.")
252
 
        else:
253
 
            raise bzrlib.errors.MustUseDecorated
 
258
        raise bzrlib.errors.MustUseDecorated
254
259
 
255
260
    if push_location.find('://') != -1:
256
261
        raise bzrlib.errors.MustUseDecorated
258
263
    if push_location.find(':') == -1:
259
264
        raise bzrlib.errors.MustUseDecorated
260
265
 
261
 
    if working_tree:
262
 
        clean, non_source = is_clean(tree)
263
 
        if not clean:
264
 
            print """Error: This tree has uncommitted changes or unknown (?) files.
265
 
    Use "bzr status" to list them."""
266
 
            sys.exit(1)
267
 
        final_exclusions = non_source[:]
268
 
    else:
269
 
        wt = tree
270
 
        final_exclusions = []
271
 
        for path, status, kind, file_id, entry in wt.list_files():
272
 
            final_exclusions.append(path)
273
 
 
274
 
    final_exclusions.extend(exclusions)
 
266
    clean, non_source = is_clean(cur_branch)
 
267
    if not clean:
 
268
        print """Error: This tree has uncommitted changes or unknown (?) files.
 
269
Use "bzr status" to list them."""
 
270
        sys.exit(1)
 
271
    non_source.extend(exclusions)
275
272
    if not overwrite:
276
273
        try:
277
 
            if not history_subset(push_location, tree.branch):
 
274
            if not history_subset(push_location, cur_branch):
278
275
                raise bzrlib.errors.BzrCommandError("Local branch is not a"
279
276
                                                    " newer version of remote"
280
277
                                                    " branch.")
288
285
                " specified location.  Please ensure that"
289
286
                ' "%s" is of the form "machine:/path".' % push_location)
290
287
    print "Pushing to %s" % push_location
291
 
    rsync(tree.basedir+'/', push_location, ssh=True, 
292
 
          excludes=final_exclusions)
293
 
 
294
 
    set_push_data(tree, push_location)
295
 
 
296
 
 
297
 
def short_committer(committer):
298
 
    new_committer = re.sub('<.*>', '', committer).strip(' ')
299
 
    if len(new_committer) < 2:
300
 
        return committer
301
 
    return new_committer
302
 
 
 
288
    rsync(cur_branch.base+'/', push_location, ssh=True, excludes=non_source)
 
289
 
 
290
    set_push_data(cur_branch, push_location)
303
291
 
304
292
def run_tests():
305
293
    import doctest