1
# Copyright (C) 2005 Aaron Bentley
2
# <aaron.bentley@utoronto.ca>
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
# GNU General Public License for more details.
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23
from subprocess import Popen, PIPE
9
26
dirname = tempfile.mkdtemp("temp-branch")
10
return bzrlib.Branch(dirname, init=True)
27
return bzrlib.branch.Branch(dirname, init=True)
13
30
shutil.rmtree(br.base)
15
32
def is_clean(cur_branch):
17
34
Return true if no files are modifed or unknown
18
36
>>> br = temp_branch()
21
39
>>> fooname = os.path.join(br.base, "foo")
22
40
>>> file(fooname, "wb").write("bar")
25
>>> bzrlib.add.smart_add([fooname])
43
>>> bzrlib.add.smart_add_branch(br, [br.base])
28
47
>>> br.commit("added file")
53
from bzrlib.diff import compare_trees
33
54
old_tree = cur_branch.basis_tree()
34
55
new_tree = cur_branch.working_tree()
35
57
for path, file_class, kind, file_id in new_tree.list_files():
38
delta = bzrlib.compare_trees(old_tree, new_tree, want_unchanged=False)
58
if file_class in ('?', 'I'):
59
non_source.append(path)
60
delta = compare_trees(old_tree, new_tree, want_unchanged=False)
39
61
if len(delta.added) > 0 or len(delta.removed) > 0 or \
40
62
len(delta.modified) > 0:
63
return False, non_source
64
return True, non_source
44
66
def set_pull_data(br, location, rev_id):
45
67
pull_file = file (br.controlfilename("x-pull-data"), "wb")
101
123
arg_str = " ".join([shell_escape(a) for a in args])
102
124
return os.system(arg_str)
104
def rsync(source, target, ssh=False, exclude_globs=()):
126
def rsync(source, target, ssh=False, excludes=()):
106
128
>>> real_system = os.system
107
129
>>> os.system = sys.stdout.write
108
130
>>> rsync("a", "b")
109
\\r\\s\\y\\n\\c \\-\\a\\v \\-\\-\\d\\e\\l\\e\\t\\e \\a \\b
110
>>> rsync("a", "b", exclude_globs=("*.py",))
111
\\r\\s\\y\\n\\c \\-\\a\\v \\-\\-\\d\\e\\l\\e\\t\\e\
112
\\-\\-\\e\\x\\c\\l\\u\\d\\e \\*\\.\\p\\y \\a \\b
131
['rsync', '-av', '--delete', 'a', 'b']
132
>>> rsync("a", "b", excludes=("*.py",))
133
['rsync', '-av', '--delete', '--exclude-from', '-', 'a', 'b']
113
134
>>> os.system = real_system
115
136
cmd = ["rsync", "-av", "--delete"]
117
138
cmd.extend(('-e', 'ssh'))
118
for exclude in exclude_globs:
119
cmd.extend(('--exclude', exclude))
139
if len(excludes) > 0:
140
cmd.extend(('--exclude-from', '-'))
120
141
cmd.extend((source, target))
123
exclusions = ('x-push-data', 'x-pull-data')
126
def pull(cur_branch, location=None, overwrite=False):
127
pull_location, pull_revision = get_pull_data(cur_branch)
128
if pull_location is not None:
129
if not overwrite and cur_branch.last_patch() != pull_revision:
130
print "Aborting: This branch has had commits, so pull would lose data."
132
if location is not None:
133
pull_location = location
134
if not pull_location.endswith('/'):
137
if pull_location is None:
138
print "No pull location saved. Please specify one on the command line."
141
if not is_clean(cur_branch):
142
print "Error: This tree has uncommitted changes or unknown (?) files."
145
print "Synchronizing with %s" % pull_location
146
rsync (pull_location, cur_branch.base+'/', exclude_globs=exclusions)
148
set_pull_data(cur_branch, pull_location, cur_branch.last_patch())
142
proc = Popen(cmd, stdin=PIPE)
143
proc.stdin.write('\n'.join(excludes)+'\n')
148
exclusions = ('.bzr/x-push-data', '.bzr/x-pull-data', '.bzr/stat-cache')
151
151
def push(cur_branch, location=None):
159
159
print "No push location saved. Please specify one on the command line."
162
if not is_clean(cur_branch):
163
print "Error: This tree has uncommitted changes or unknown (?) files."
162
clean, non_source = is_clean(cur_branch)
164
print """Error: This tree has uncommitted changes or unknown (?) files.
165
Use "bzr status" to list them."""
167
non_source.extend(exclusions)
166
169
print "Pushing to %s" % push_location
167
rsync(cur_branch.base+'/', push_location, ssh=True,
168
exclude_globs=exclusions)
170
rsync(cur_branch.base+'/', push_location, ssh=True, excludes=non_source)
170
172
set_push_data(cur_branch, push_location)