40
50
def is_clean(cur_tree):
42
52
Return true if no files are modifed or unknown
44
>>> tree = temp_tree()
47
>>> fooname = os.path.join(tree.basedir, "foo")
48
>>> file(fooname, "wb").write("bar")
51
>>> bzrlib.add.smart_add_tree(tree, [tree.basedir])
55
>>> tree.commit("added file", rev_id='commit-id')
61
54
old_tree = cur_tree.basis_tree()
62
55
new_tree = cur_tree
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 = new_tree.changes_from(old_tree, want_unchanged=False)
59
for path, file_class, kind, file_id, entry in new_tree.list_files():
60
if file_class in ('?', 'I'):
61
non_source.append(path)
62
delta = new_tree.changes_from(old_tree, want_unchanged=False)
68
65
return not delta.has_changed(), non_source
70
67
def set_push_data(tree, location):
189
187
raise RsyncUnknownStatus(proc.returncode)
190
188
return [l.split(' ')[-1].rstrip('\n') for l in result.splitlines(True)]
192
exclusions = ('.bzr/x-push-data', '.bzr/branch/x-push/data', '.bzr/parent',
190
exclusions = ('.bzr/x-push-data', '.bzr/branch/x-push/data', '.bzr/parent',
193
191
'.bzr/branch/parent', '.bzr/x-pull-data', '.bzr/x-pull',
194
192
'.bzr/pull', '.bzr/stat-cache', '.bzr/x-rsync-data',
195
193
'.bzr/basis-inventory', '.bzr/inventory.backup.weave')
207
205
def __init__(self):
208
206
Exception.__init__(self, "Error in rsync protocol data stream.")
210
def get_revision_history(location):
209
class NotStandalone(BzrError):
211
_format = '%(location) is not a standalone tree.'
214
def __init__(self, location):
215
BzrError.__init__(self, location=location)
218
def get_revision_history(location, _rsync):
211
219
tempdir = tempfile.mkdtemp('push')
213
224
history_fname = os.path.join(tempdir, 'revision-history')
215
cmd = rsync(location+'.bzr/revision-history', history_fname,
226
cmd = my_rsync(location+'.bzr/revision-history', history_fname,
217
228
except RsyncNoFile:
218
229
cmd = rsync(location+'.bzr/branch/revision-history', history_fname,
239
251
except RsyncNoFile:
242
def rspush(tree, location=None, overwrite=False, working_tree=True):
243
push_location = get_push_data(tree)
244
if location is not None:
245
if not location.endswith('/'):
247
push_location = location
249
if push_location is None:
250
raise BzrCommandError("No rspush location known or specified.")
252
if (push_location.find('::') != -1):
257
if (push_location.find('://') != -1 or
258
push_location.find(':') == -1):
259
raise BzrCommandError("Invalid rsync path %r." % push_location)
262
clean, non_source = is_clean(tree)
264
print """Error: This tree has uncommitted changes or unknown (?) files.
265
Use "bzr status" to list them."""
267
final_exclusions = non_source[:]
270
final_exclusions = []
271
for path, status, kind, file_id, entry in wt.list_files():
272
final_exclusions.append(path)
274
final_exclusions.extend(exclusions)
277
if not history_subset(push_location, tree.branch):
278
raise bzrlib.errors.BzrCommandError("Local branch is not a"
279
" newer version of remote"
282
if not empty_or_absent(push_location):
283
raise bzrlib.errors.BzrCommandError("Remote location is not a"
284
" bzr branch (or empty"
286
except RsyncStreamIO:
287
raise bzrlib.errors.BzrCommandError("Rsync could not use the"
288
" specified location. Please ensure that"
289
' "%s" is of the form "machine:/path".' % push_location)
290
print "Pushing to %s" % push_location
291
rsync(tree.basedir+'/', push_location, ssh=usessh,
292
excludes=final_exclusions)
294
set_push_data(tree, push_location)
254
def rspush(tree, location=None, overwrite=False, working_tree=True,
261
if (tree.bzrdir.root_transport.base !=
262
tree.branch.bzrdir.root_transport.base):
263
raise NotStandalone(tree.bzrdir.root_transport.base)
264
if (tree.branch.get_bound_location() is not None):
265
raise NotStandalone(tree.bzrdir.root_transport.base)
266
if (tree.branch.repository.is_shared()):
267
raise NotStandalone(tree.bzrdir.root_transport.base)
268
push_location = get_push_data(tree)
269
if location is not None:
270
if not location.endswith('/'):
272
push_location = location
274
if push_location is None:
275
raise BzrCommandError("No rspush location known or specified.")
277
if (push_location.find('::') != -1):
282
if (push_location.find('://') != -1 or
283
push_location.find(':') == -1):
284
raise BzrCommandError("Invalid rsync path %r." % push_location)
287
clean, non_source = is_clean(tree)
289
raise bzrlib.errors.BzrCommandError(
290
'This tree has uncommitted changes or unknown'
291
' (?) files. Use "bzr status" to list them.')
293
final_exclusions = non_source[:]
296
final_exclusions = []
297
for path, status, kind, file_id, entry in wt.list_files():
298
final_exclusions.append(path)
300
final_exclusions.extend(exclusions)
303
if not history_subset(push_location, tree.branch,
305
raise bzrlib.errors.BzrCommandError(
306
"Local branch is not a newer version of remote"
309
if not empty_or_absent(push_location):
310
raise bzrlib.errors.BzrCommandError(
311
"Remote location is not a bzr branch (or empty"
313
except RsyncStreamIO:
314
raise bzrlib.errors.BzrCommandError("Rsync could not use the"
315
" specified location. Please ensure that"
316
' "%s" is of the form "machine:/path".' % push_location)
317
trace.note("Pushing to %s", push_location)
318
my_rsync(tree.basedir+'/', push_location, ssh=usessh,
319
excludes=final_exclusions)
321
set_push_data(tree, push_location)
297
326
def short_committer(committer):
319
353
yield url.rstrip('/')
322
def iter_branches(t, lister=None):
323
"""Iterate through all the branches under a transport"""
324
for bzrdir in iter_bzrdirs(t, lister):
326
branch = bzrdir.open_branch()
327
if branch.bzrdir is bzrdir:
329
except (NotBranchError, UnsupportedFormatError):
356
def list_branches(t):
357
def is_inside(branch):
358
return bool(branch.base.startswith(t.base))
360
if t.base.startswith('http://'):
361
def evaluate(bzrdir):
363
branch = bzrdir.open_branch()
364
if is_inside(branch):
368
except NotBranchError:
370
return [b for b in BzrDir.find_bzrdirs(t, list_current=apache_ls,
371
evaluate=evaluate) if b is not None]
372
elif not t.listable():
373
raise BzrCommandError("Can't list this type of location.")
374
return [b for b in BzrDir.find_branches(t) if is_inside(b)]
377
def evaluate_branch_tree(bzrdir):
379
tree, branch = bzrdir._get_tree_branch()
380
except NotBranchError:
383
return True, (branch, tree)
333
386
def iter_branch_tree(t, lister=None):
334
for bzrdir in iter_bzrdirs(t, lister):
336
wt = bzrdir.open_workingtree()
338
except NoWorkingTree, UnsupportedFormatError:
340
branch = bzrdir.open_branch()
341
if branch.bzrdir is bzrdir:
343
except (NotBranchError, UnsupportedFormatError):
347
def iter_bzrdirs(t, lister=None):
350
return t.list_dir('.')
352
bzrdir = bzrdir_from_transport(t)
354
except (NotBranchError, UnsupportedFormatError, TransportError,
358
for directory in lister(t):
359
if directory == ".bzr":
362
subt = t.clone(directory)
363
except UnicodeDecodeError:
365
for bzrdir in iter_bzrdirs(subt, lister):
367
except (NoSuchFile, PermissionDenied, TransportError):
371
def bzrdir_from_transport(t):
372
"""Open a bzrdir from a transport (not a location)"""
373
format = BzrDirFormat.find_format(t)
374
BzrDir._check_supported(format, False)
375
return format.open(t)
387
return (x for x in BzrDir.find_bzrdirs(t, evaluate=evaluate_branch_tree,
388
list_current=lister) if x is not None)
391
def open_from_url(location):
392
location = urlutils.normalize_url(location)
393
dirname, basename = urlutils.split(location)
394
return get_transport(dirname).get(basename)