~abentley/bzrtools/bzrtools.dev

« back to all changes in this revision

Viewing changes to bzrtools.py

  • Committer: Aaron Bentley
  • Date: 2006-03-16 14:53:00 UTC
  • mfrom: (0.1.96 shelf)
  • mto: This revision was merged to the branch mainline in revision 334.
  • Revision ID: abentley@panoramicfeedback.com-20060316145300-836889d55437eb15
Merge shelf v2

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007 Aaron Bentley <aaron.bentley@utoronto.ca>
2
 
# Copyright (C) 2007 John Arbash Meinel
 
1
# Copyright (C) 2005 Aaron Bentley
 
2
# <aaron.bentley@utoronto.ca>
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
25
25
 
26
26
import bzrlib
27
27
import bzrlib.errors
28
 
from bzrlib.errors import (BzrCommandError, NotBranchError, NoSuchFile,
29
 
                           UnsupportedFormatError, TransportError, 
30
 
                           NoWorkingTree, PermissionDenied)
31
 
from bzrlib.bzrdir import BzrDir, BzrDirFormat
 
28
from bzrlib.errors import BzrCommandError
 
29
from bzrlib.bzrdir import BzrDir
32
30
 
33
31
def temp_tree():
34
32
    dirname = tempfile.mkdtemp("temp-branch")
40
38
def is_clean(cur_tree):
41
39
    """
42
40
    Return true if no files are modifed or unknown
 
41
    >>> import bzrlib.add
 
42
    >>> tree = temp_tree()
 
43
    >>> is_clean(tree)
 
44
    (True, [])
 
45
    >>> fooname = os.path.join(tree.basedir, "foo")
 
46
    >>> file(fooname, "wb").write("bar")
 
47
    >>> is_clean(tree)
 
48
    (True, [u'foo'])
 
49
    >>> bzrlib.add.smart_add_tree(tree, [tree.basedir])
 
50
    ([u'foo'], {})
 
51
    >>> is_clean(tree)
 
52
    (False, [])
 
53
    >>> tree.commit("added file")
 
54
    >>> is_clean(tree)
 
55
    (True, [])
 
56
    >>> rm_tree(tree)
43
57
    """
 
58
    from bzrlib.diff import compare_trees
44
59
    old_tree = cur_tree.basis_tree()
45
60
    new_tree = cur_tree
46
61
    non_source = []
47
 
    new_tree.lock_read()
48
 
    try:
49
 
        for path, file_class, kind, file_id, entry in new_tree.list_files():
50
 
            if file_class in ('?', 'I'):
51
 
                non_source.append(path)
52
 
        delta = new_tree.changes_from(old_tree, want_unchanged=False)
53
 
    finally:
54
 
        new_tree.unlock()
 
62
    for path, file_class, kind, file_id, entry in new_tree.list_files():
 
63
        if file_class in ('?', 'I'):
 
64
            non_source.append(path)
 
65
    delta = compare_trees(old_tree, new_tree, want_unchanged=False)
55
66
    return not delta.has_changed(), non_source
56
67
 
57
68
def set_push_data(tree, location):
58
 
    tree.branch.control_files.put_utf8("x-push-data", "%s\n" % location)
 
69
    push_file = file (tree._control_files.controlfilename("x-push-data"), "wb")
 
70
    push_file.write("%s\n" % location)
59
71
 
60
72
def get_push_data(tree):
61
73
    """
64
76
    True
65
77
    >>> set_push_data(tree, 'http://somewhere')
66
78
    >>> get_push_data(tree)
67
 
    u'http://somewhere'
 
79
    'http://somewhere'
68
80
    >>> rm_tree(tree)
69
81
    """
70
 
    try:
71
 
        location = tree.branch.control_files.get_utf8('x-push-data').read()
72
 
    except NoSuchFile:
 
82
    filename = tree._control_files.controlfilename("x-push-data")
 
83
    if not os.path.exists(filename):
73
84
        return None
74
 
    return location.rstrip('\n')
 
85
    push_file = file (filename, "rb")
 
86
    (location,) = [f.rstrip('\n') for f in push_file]
 
87
    return location
75
88
 
76
89
"""
77
90
>>> shell_escape('hello')
176
189
        raise RsyncUnknownStatus(proc.returncode)
177
190
    return [l.split(' ')[-1].rstrip('\n') for l in result.splitlines(True)]
178
191
 
179
 
exclusions = ('.bzr/x-push-data', '.bzr/branch/x-push/data', '.bzr/parent', 
180
 
              '.bzr/branch/parent', '.bzr/x-pull-data', '.bzr/x-pull',
181
 
              '.bzr/pull', '.bzr/stat-cache', '.bzr/x-rsync-data',
182
 
              '.bzr/basis-inventory', '.bzr/inventory.backup.weave')
 
192
exclusions = ('.bzr/x-push-data', '.bzr/parent', '.bzr/x-pull-data', 
 
193
              '.bzr/x-pull', '.bzr/pull', '.bzr/stat-cache',
 
194
              '.bzr/x-rsync-data', '.bzr/basis-inventory', 
 
195
              '.bzr/inventory.backup.weave')
183
196
 
184
197
 
185
198
def read_revision_history(fname):
198
211
    tempdir = tempfile.mkdtemp('push')
199
212
    try:
200
213
        history_fname = os.path.join(tempdir, 'revision-history')
201
 
        try:
202
 
            cmd = rsync(location+'.bzr/revision-history', history_fname,
203
 
                        silent=True)
204
 
        except RsyncNoFile:
205
 
            cmd = rsync(location+'.bzr/branch/revision-history', history_fname,
206
 
                        silent=True)
 
214
        cmd = rsync(location+'.bzr/revision-history', history_fname,
 
215
                    silent=True)
207
216
        history = read_revision_history(history_fname)
208
217
    finally:
209
218
        shutil.rmtree(tempdir)
226
235
    except RsyncNoFile:
227
236
        return True
228
237
 
229
 
def rspush(tree, location=None, overwrite=False, working_tree=True):
 
238
def push(tree, location=None, overwrite=False, working_tree=True):
230
239
    push_location = get_push_data(tree)
231
240
    if location is not None:
232
241
        if not location.endswith('/'):
234
243
        push_location = location
235
244
    
236
245
    if push_location is None:
237
 
        raise BzrCommandError("No rspush location known or specified.")
238
 
 
239
 
    if (push_location.find('::') != -1):
240
 
        usessh=False
241
 
    else:
242
 
        usessh=True
243
 
 
244
 
    if (push_location.find('://') != -1 or
245
 
        push_location.find(':') == -1):
246
 
        raise BzrCommandError("Invalid rsync path %r." % push_location)
247
 
 
 
246
        if tree.branch.get_push_location() is None:
 
247
            raise BzrCommandError("No push location known or specified.")
 
248
        else:
 
249
            raise bzrlib.errors.MustUseDecorated
 
250
 
 
251
    if push_location.find('://') != -1:
 
252
        raise bzrlib.errors.MustUseDecorated
 
253
 
 
254
    if push_location.find(':') == -1:
 
255
        raise bzrlib.errors.MustUseDecorated
 
256
 
 
257
    clean, non_source = is_clean(tree)
 
258
    if not clean:
 
259
        print """Error: This tree has uncommitted changes or unknown (?) files.
 
260
Use "bzr status" to list them."""
 
261
        sys.exit(1)
248
262
    if working_tree:
249
 
        clean, non_source = is_clean(tree)
250
 
        if not clean:
251
 
            print """Error: This tree has uncommitted changes or unknown (?) files.
252
 
    Use "bzr status" to list them."""
253
 
            sys.exit(1)
254
263
        final_exclusions = non_source[:]
255
264
    else:
256
265
        wt = tree
275
284
                " specified location.  Please ensure that"
276
285
                ' "%s" is of the form "machine:/path".' % push_location)
277
286
    print "Pushing to %s" % push_location
278
 
    rsync(tree.basedir+'/', push_location, ssh=usessh, 
 
287
    rsync(tree.basedir+'/', push_location, ssh=True, 
279
288
          excludes=final_exclusions)
280
289
 
281
290
    set_push_data(tree, push_location)
288
297
    return new_committer
289
298
 
290
299
 
291
 
def apache_ls(t):
292
 
    """Screen-scrape Apache listings"""
293
 
    apache_dir = '<img border="0" src="/icons/folder.gif" alt="[dir]">'\
294
 
        ' <a href="'
295
 
    lines = t.get('.')
296
 
    expr = re.compile('<a[^>]*href="([^>]*)"[^>]*>', flags=re.I)
297
 
    for line in lines:
298
 
        match = expr.search(line)
299
 
        if match is None:
300
 
            continue
301
 
        url = match.group(1)
302
 
        if url.startswith('http://') or url.startswith('/') or '../' in url:
303
 
            continue
304
 
        if '?' in url:
305
 
            continue
306
 
        yield url.rstrip('/')
307
 
 
308
 
 
309
 
def iter_branches(t, lister=None):
310
 
    """Iterate through all the branches under a transport"""
311
 
    for bzrdir in iter_bzrdirs(t, lister):
312
 
        try:
313
 
            branch = bzrdir.open_branch()
314
 
            if branch.bzrdir is bzrdir:
315
 
                yield branch
316
 
        except (NotBranchError, UnsupportedFormatError):
317
 
            pass
318
 
 
319
 
 
320
 
def iter_branch_tree(t, lister=None):
321
 
    for bzrdir in iter_bzrdirs(t, lister):
322
 
        try:
323
 
            wt = bzrdir.open_workingtree()
324
 
            yield wt.branch, wt
325
 
        except NoWorkingTree, UnsupportedFormatError:
326
 
            try:
327
 
                branch = bzrdir.open_branch()
328
 
                if branch.bzrdir is bzrdir:
329
 
                    yield branch, None
330
 
            except (NotBranchError, UnsupportedFormatError):
331
 
                continue
332
 
 
333
 
 
334
 
def iter_bzrdirs(t, lister=None):
335
 
    if lister is None:
336
 
        def lister(t):
337
 
            return t.list_dir('.')
338
 
    try:
339
 
        bzrdir = bzrdir_from_transport(t)
340
 
        yield bzrdir
341
 
    except (NotBranchError, UnsupportedFormatError, TransportError,
342
 
            PermissionDenied):
343
 
        pass
344
 
    try:
345
 
        for directory in lister(t):
346
 
            if directory == ".bzr":
347
 
                continue
348
 
            try:
349
 
                subt = t.clone(directory)
350
 
            except UnicodeDecodeError:
351
 
                continue
352
 
            for bzrdir in iter_bzrdirs(subt, lister):
353
 
                yield bzrdir
354
 
    except (NoSuchFile, PermissionDenied, TransportError):
355
 
        pass
356
 
 
357
 
    
358
 
def bzrdir_from_transport(t):
359
 
    """Open a bzrdir from a transport (not a location)"""
360
 
    format = BzrDirFormat.find_format(t)
361
 
    BzrDir._check_supported(format, False)
362
 
    return format.open(t)
363
 
 
364
 
 
365
300
def run_tests():
366
301
    import doctest
367
302
    result = doctest.testmod()