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>
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
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
34
32
dirname = tempfile.mkdtemp("temp-branch")
40
38
def is_clean(cur_tree):
42
40
Return true if no files are modifed or unknown
42
>>> tree = temp_tree()
45
>>> fooname = os.path.join(tree.basedir, "foo")
46
>>> file(fooname, "wb").write("bar")
49
>>> bzrlib.add.smart_add_tree(tree, [tree.basedir])
53
>>> tree.commit("added file")
58
from bzrlib.diff import compare_trees
44
59
old_tree = cur_tree.basis_tree()
45
60
new_tree = cur_tree
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)
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
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)
60
72
def get_push_data(tree):
65
77
>>> set_push_data(tree, 'http://somewhere')
66
78
>>> get_push_data(tree)
71
location = tree.branch.control_files.get_utf8('x-push-data').read()
82
filename = tree._control_files.controlfilename("x-push-data")
83
if not os.path.exists(filename):
74
return location.rstrip('\n')
85
push_file = file (filename, "rb")
86
(location,) = [f.rstrip('\n') for f in push_file]
77
90
>>> shell_escape('hello')
99
112
def __init__(self, rsync_name):
100
113
Exception.__init__(self, "%s not found." % rsync_name)
102
def rsync(source, target, ssh=False, excludes=(), silent=False,
115
def rsync(source, target, ssh=False, excludes=(), silent=False,
103
116
rsync_name="rsync"):
105
118
>>> new_dir = tempfile.mkdtemp()
108
121
>>> rsync("a", "b", silent=True)
109
122
Traceback (most recent call last):
110
123
RsyncNoFile: No such file...
111
>>> rsync(new_dir + "/a", new_dir + "/b", excludes=("*.py",), silent=True)
124
>>> rsync(tempdir + "/a", tempdir + "/b", excludes=("*.py",), silent=True) #doctest: +ELLIPSIS
112
125
Traceback (most recent call last):
113
126
RsyncNoFile: No such file...
114
>>> rsync(new_dir + "/a", new_dir + "/b", excludes=("*.py",), silent=True, rsync_name="rsyncc")
127
>>> rsync(tempdir + "/a", tempdir + "/b", excludes=("*.py",), silent=True, rsync_name="rsyncc")
115
128
Traceback (most recent call last):
116
129
NoRsync: rsyncc not found.
117
130
>>> os.chdir(old_dir)
176
189
raise RsyncUnknownStatus(proc.returncode)
177
190
return [l.split(' ')[-1].rstrip('\n') for l in result.splitlines(True)]
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',
185
197
def read_revision_history(fname):
198
210
tempdir = tempfile.mkdtemp('push')
200
212
history_fname = os.path.join(tempdir, 'revision-history')
202
cmd = rsync(location+'.bzr/revision-history', history_fname,
205
cmd = rsync(location+'.bzr/branch/revision-history', history_fname,
213
cmd = rsync(location+'.bzr/revision-history', history_fname,
207
215
history = read_revision_history(history_fname)
209
217
shutil.rmtree(tempdir)
226
234
except RsyncNoFile:
229
def rspush(tree, location=None, overwrite=False, working_tree=True):
237
def push(tree, location=None, overwrite=False, working_tree=True):
230
238
push_location = get_push_data(tree)
231
239
if location is not None:
232
240
if not location.endswith('/'):
234
242
push_location = location
236
244
if push_location is None:
237
raise BzrCommandError("No rspush location known or specified.")
239
if (push_location.find('::') != -1):
244
if (push_location.find('://') != -1 or
245
push_location.find(':') == -1):
246
raise BzrCommandError("Invalid rsync path %r." % push_location)
245
if tree.branch.get_push_location() is None:
246
raise BzrCommandError("No push location known or specified.")
248
raise bzrlib.errors.MustUseDecorated
250
if push_location.find('://') != -1:
251
raise bzrlib.errors.MustUseDecorated
253
if push_location.find(':') == -1:
254
raise bzrlib.errors.MustUseDecorated
256
clean, non_source = is_clean(tree)
258
print """Error: This tree has uncommitted changes or unknown (?) files.
259
Use "bzr status" to list them."""
249
clean, non_source = is_clean(tree)
251
print """Error: This tree has uncommitted changes or unknown (?) files.
252
Use "bzr status" to list them."""
254
262
final_exclusions = non_source[:]
275
283
" specified location. Please ensure that"
276
284
' "%s" is of the form "machine:/path".' % push_location)
277
285
print "Pushing to %s" % push_location
278
rsync(tree.basedir+'/', push_location, ssh=usessh,
286
rsync(tree.basedir+'/', push_location, ssh=True,
279
287
excludes=final_exclusions)
281
289
set_push_data(tree, push_location)
288
296
return new_committer
292
"""Screen-scrape Apache listings"""
293
apache_dir = '<img border="0" src="/icons/folder.gif" alt="[dir]">'\
296
expr = re.compile('<a[^>]*href="([^>]*)"[^>]*>', flags=re.I)
298
match = expr.search(line)
302
if url.startswith('http://') or url.startswith('/') or '../' in url:
306
yield url.rstrip('/')
309
def iter_branches(t, lister=None):
310
"""Iterate through all the branches under a transport"""
311
for bzrdir in iter_bzrdirs(t, lister):
313
branch = bzrdir.open_branch()
314
if branch.bzrdir is bzrdir:
316
except (NotBranchError, UnsupportedFormatError):
320
def iter_branch_tree(t, lister=None):
321
for bzrdir in iter_bzrdirs(t, lister):
323
wt = bzrdir.open_workingtree()
325
except NoWorkingTree, UnsupportedFormatError:
327
branch = bzrdir.open_branch()
328
if branch.bzrdir is bzrdir:
330
except (NotBranchError, UnsupportedFormatError):
334
def iter_bzrdirs(t, lister=None):
337
return t.list_dir('.')
339
bzrdir = bzrdir_from_transport(t)
341
except (NotBranchError, UnsupportedFormatError, TransportError,
345
for directory in lister(t):
346
if directory == ".bzr":
349
subt = t.clone(directory)
350
except UnicodeDecodeError:
352
for bzrdir in iter_bzrdirs(subt, lister):
354
except (NoSuchFile, PermissionDenied, TransportError):
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)
367
301
result = doctest.testmod()