~abentley/bzrtools/bzrtools.dev

« back to all changes in this revision

Viewing changes to bzrtools.py

  • Committer: Aaron Bentley
  • Date: 2007-08-16 03:30:21 UTC
  • mto: This revision was merged to the branch mainline in revision 576.
  • Revision ID: aaron.bentley@utoronto.ca-20070816033021-e9k6t6rj25ndlhrk
Allow zap --force to delete modified checkouts

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005 Aaron Bentley
2
 
# <aaron.bentley@utoronto.ca>
 
1
# Copyright (C) 2005, 2006, 2007 Aaron Bentley <aaron.bentley@utoronto.ca>
 
2
# Copyright (C) 2007 John Arbash Meinel
3
3
#
4
4
#    This program is free software; you can redistribute it and/or modify
5
5
#    it under the terms of the GNU General Public License as published by
24
24
import sys
25
25
 
26
26
import bzrlib
 
27
from bzrlib import urlutils
27
28
import bzrlib.errors
28
29
from bzrlib.errors import (BzrCommandError, NotBranchError, NoSuchFile,
29
 
                           UnsupportedFormatError, TransportError, 
30
 
                           NoWorkingTree, PermissionDenied)
 
30
                           UnsupportedFormatError, TransportError,
 
31
                           NoWorkingTree, PermissionDenied, ConnectionError)
31
32
from bzrlib.bzrdir import BzrDir, BzrDirFormat
 
33
from bzrlib.transport import get_transport
32
34
 
33
35
def temp_tree():
34
36
    dirname = tempfile.mkdtemp("temp-branch")
40
42
def is_clean(cur_tree):
41
43
    """
42
44
    Return true if no files are modifed or unknown
43
 
    >>> import bzrlib.add
44
 
    >>> tree = temp_tree()
45
 
    >>> is_clean(tree)
46
 
    (True, [])
47
 
    >>> fooname = os.path.join(tree.basedir, "foo")
48
 
    >>> file(fooname, "wb").write("bar")
49
 
    >>> is_clean(tree)
50
 
    (True, [u'foo'])
51
 
    >>> bzrlib.add.smart_add_tree(tree, [tree.basedir])
52
 
    ([u'foo'], {})
53
 
    >>> is_clean(tree)
54
 
    (False, [])
55
 
    >>> tree.commit("added file")
56
 
    >>> is_clean(tree)
57
 
    (True, [])
58
 
    >>> rm_tree(tree)
59
45
    """
60
 
    from bzrlib.diff import compare_trees
61
46
    old_tree = cur_tree.basis_tree()
62
47
    new_tree = cur_tree
63
48
    non_source = []
64
 
    for path, file_class, kind, file_id, entry in new_tree.list_files():
65
 
        if file_class in ('?', 'I'):
66
 
            non_source.append(path)
67
 
    delta = compare_trees(old_tree, new_tree, want_unchanged=False)
 
49
    new_tree.lock_read()
 
50
    try:
 
51
        for path, file_class, kind, file_id, entry in new_tree.list_files():
 
52
            if file_class in ('?', 'I'):
 
53
                non_source.append(path)
 
54
        delta = new_tree.changes_from(old_tree, want_unchanged=False)
 
55
    finally:
 
56
        new_tree.unlock()
68
57
    return not delta.has_changed(), non_source
69
58
 
70
59
def set_push_data(tree, location):
71
 
    push_file = file (tree.branch.control_files.controlfilename("x-push-data"), "wb")
72
 
    push_file.write("%s\n" % location)
 
60
    tree.branch.control_files.put_utf8("x-push-data", "%s\n" % location)
73
61
 
74
62
def get_push_data(tree):
75
63
    """
78
66
    True
79
67
    >>> set_push_data(tree, 'http://somewhere')
80
68
    >>> get_push_data(tree)
81
 
    'http://somewhere'
 
69
    u'http://somewhere'
82
70
    >>> rm_tree(tree)
83
71
    """
84
 
    filename = tree.branch.control_files.controlfilename("x-push-data")
85
 
    if not os.path.exists(filename):
 
72
    try:
 
73
        location = tree.branch.control_files.get_utf8('x-push-data').read()
 
74
    except NoSuchFile:
86
75
        return None
87
 
    push_file = file (filename, "rb")
88
 
    (location,) = [f.rstrip('\n') for f in push_file]
89
 
    return location
 
76
    return location.rstrip('\n')
90
77
 
91
78
"""
92
79
>>> shell_escape('hello')
114
101
    def __init__(self, rsync_name):
115
102
        Exception.__init__(self, "%s not found." % rsync_name)
116
103
 
117
 
def rsync(source, target, ssh=False, excludes=(), silent=False, 
 
104
def rsync(source, target, ssh=False, excludes=(), silent=False,
118
105
          rsync_name="rsync"):
119
106
    """
120
107
    >>> new_dir = tempfile.mkdtemp()
149
136
    except OSError, e:
150
137
        if e.errno == errno.ENOENT:
151
138
            raise NoRsync(rsync_name)
152
 
            
 
139
 
153
140
    proc.stdin.write('\n'.join(excludes)+'\n')
154
141
    proc.stdin.close()
155
142
    if silent:
191
178
        raise RsyncUnknownStatus(proc.returncode)
192
179
    return [l.split(' ')[-1].rstrip('\n') for l in result.splitlines(True)]
193
180
 
194
 
exclusions = ('.bzr/x-push-data', '.bzr/branch/x-push/data', '.bzr/parent', 
 
181
exclusions = ('.bzr/x-push-data', '.bzr/branch/x-push/data', '.bzr/parent',
195
182
              '.bzr/branch/parent', '.bzr/x-pull-data', '.bzr/x-pull',
196
183
              '.bzr/pull', '.bzr/stat-cache', '.bzr/x-rsync-data',
197
184
              '.bzr/basis-inventory', '.bzr/inventory.backup.weave')
231
218
        return False
232
219
    for local, remote in zip(remote_history, local_history):
233
220
        if local != remote:
234
 
            return False 
 
221
            return False
235
222
    return True
236
223
 
237
224
def empty_or_absent(location):
247
234
        if not location.endswith('/'):
248
235
            location += '/'
249
236
        push_location = location
250
 
    
 
237
 
251
238
    if push_location is None:
252
239
        raise BzrCommandError("No rspush location known or specified.")
253
240
 
 
241
    if (push_location.find('::') != -1):
 
242
        usessh=False
 
243
    else:
 
244
        usessh=True
 
245
 
254
246
    if (push_location.find('://') != -1 or
255
247
        push_location.find(':') == -1):
256
248
        raise BzrCommandError("Invalid rsync path %r." % push_location)
285
277
                " specified location.  Please ensure that"
286
278
                ' "%s" is of the form "machine:/path".' % push_location)
287
279
    print "Pushing to %s" % push_location
288
 
    rsync(tree.basedir+'/', push_location, ssh=True, 
 
280
    rsync(tree.basedir+'/', push_location, ssh=usessh,
289
281
          excludes=final_exclusions)
290
282
 
291
283
    set_push_data(tree, push_location)
302
294
    """Screen-scrape Apache listings"""
303
295
    apache_dir = '<img border="0" src="/icons/folder.gif" alt="[dir]">'\
304
296
        ' <a href="'
305
 
    lines = t.get('.')
 
297
    t = t.clone()
 
298
    t._remote_path = lambda x: t.base
 
299
    lines = t.get('')
306
300
    expr = re.compile('<a[^>]*href="([^>]*)"[^>]*>', flags=re.I)
307
301
    for line in lines:
308
302
        match = expr.search(line)
348
342
    try:
349
343
        bzrdir = bzrdir_from_transport(t)
350
344
        yield bzrdir
 
345
    except (ConnectionError):
 
346
        raise
351
347
    except (NotBranchError, UnsupportedFormatError, TransportError,
352
348
            PermissionDenied):
353
349
        pass
364
360
    except (NoSuchFile, PermissionDenied, TransportError):
365
361
        pass
366
362
 
367
 
    
 
363
 
368
364
def bzrdir_from_transport(t):
369
365
    """Open a bzrdir from a transport (not a location)"""
370
366
    format = BzrDirFormat.find_format(t)
372
368
    return format.open(t)
373
369
 
374
370
 
 
371
def open_from_url(location):
 
372
    location = urlutils.normalize_url(location)
 
373
    dirname, basename = urlutils.split(location)
 
374
    return get_transport(dirname).get(basename)
 
375
 
 
376
 
375
377
def run_tests():
376
378
    import doctest
377
379
    result = doctest.testmod()