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
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
29
from bzrlib.bzrdir import BzrDir
28
from bzrlib.errors import (BzrCommandError, NotBranchError, NoSuchFile,
29
UnsupportedFormatError, TransportError,
30
NoWorkingTree, PermissionDenied)
31
from bzrlib.bzrdir import BzrDir, BzrDirFormat
32
34
dirname = tempfile.mkdtemp("temp-branch")
38
40
def is_clean(cur_tree):
40
42
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
59
44
old_tree = cur_tree.basis_tree()
60
45
new_tree = cur_tree
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)
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)
66
55
return not delta.has_changed(), non_source
68
57
def set_push_data(tree, location):
69
push_file = file (tree._control_files.controlfilename("x-push-data"), "wb")
70
push_file.write("%s\n" % location)
58
tree.branch.control_files.put_utf8("x-push-data", "%s\n" % location)
72
60
def get_push_data(tree):
77
65
>>> set_push_data(tree, 'http://somewhere')
78
66
>>> get_push_data(tree)
82
filename = tree._control_files.controlfilename("x-push-data")
83
if not os.path.exists(filename):
71
location = tree.branch.control_files.get_utf8('x-push-data').read()
85
push_file = file (filename, "rb")
86
(location,) = [f.rstrip('\n') for f in push_file]
74
return location.rstrip('\n')
90
77
>>> shell_escape('hello')
112
99
def __init__(self, rsync_name):
113
100
Exception.__init__(self, "%s not found." % rsync_name)
115
def rsync(source, target, ssh=False, excludes=(), silent=False,
102
def rsync(source, target, ssh=False, excludes=(), silent=False,
116
103
rsync_name="rsync"):
118
105
>>> new_dir = tempfile.mkdtemp()
189
176
raise RsyncUnknownStatus(proc.returncode)
190
177
return [l.split(' ')[-1].rstrip('\n') for l in result.splitlines(True)]
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')
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')
198
185
def read_revision_history(fname):
211
198
tempdir = tempfile.mkdtemp('push')
213
200
history_fname = os.path.join(tempdir, 'revision-history')
214
cmd = rsync(location+'.bzr/revision-history', history_fname,
202
cmd = rsync(location+'.bzr/revision-history', history_fname,
205
cmd = rsync(location+'.bzr/branch/revision-history', history_fname,
216
207
history = read_revision_history(history_fname)
218
209
shutil.rmtree(tempdir)
235
226
except RsyncNoFile:
238
def push(tree, location=None, overwrite=False, working_tree=True):
229
def rspush(tree, location=None, overwrite=False, working_tree=True):
239
230
push_location = get_push_data(tree)
240
231
if location is not None:
241
232
if not location.endswith('/'):
243
234
push_location = location
245
236
if push_location is None:
246
if tree.branch.get_push_location() is None:
247
raise BzrCommandError("No push location known or specified.")
249
raise bzrlib.errors.MustUseDecorated
251
if push_location.find('://') != -1:
252
raise bzrlib.errors.MustUseDecorated
254
if push_location.find(':') == -1:
255
raise bzrlib.errors.MustUseDecorated
257
clean, non_source = is_clean(tree)
259
print """Error: This tree has uncommitted changes or unknown (?) files.
260
Use "bzr status" to list them."""
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)
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."""
263
254
final_exclusions = non_source[:]
284
275
" specified location. Please ensure that"
285
276
' "%s" is of the form "machine:/path".' % push_location)
286
277
print "Pushing to %s" % push_location
287
rsync(tree.basedir+'/', push_location, ssh=True,
278
rsync(tree.basedir+'/', push_location, ssh=usessh,
288
279
excludes=final_exclusions)
290
281
set_push_data(tree, push_location)
297
288
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)
302
367
result = doctest.testmod()