14
14
# You should have received a copy of the GNU General Public License
15
15
# along with this program; if not, write to the Free Software
16
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23
from subprocess import Popen, PIPE
26
dirname = tempfile.mkdtemp("temp-branch")
27
return bzrlib.branch.Branch(dirname, init=True)
30
shutil.rmtree(br.base)
32
def is_clean(cur_branch):
34
Return true if no files are modifed or unknown
36
>>> br = temp_branch()
39
>>> fooname = os.path.join(br.base, "foo")
40
>>> file(fooname, "wb").write("bar")
43
>>> bzrlib.add.smart_add_branch(br, [br.base])
47
>>> br.commit("added file")
53
from bzrlib.diff import compare_trees
54
old_tree = cur_branch.basis_tree()
55
new_tree = cur_branch.working_tree()
57
for path, file_class, kind, file_id in new_tree.list_files():
58
if file_class in ('?', 'I'):
59
non_source.append(path)
60
delta = compare_trees(old_tree, new_tree, want_unchanged=False)
61
if len(delta.added) > 0 or len(delta.removed) > 0 or \
62
len(delta.modified) > 0:
63
return False, non_source
64
return True, non_source
66
def set_pull_data(br, location, rev_id):
67
pull_file = file (br.controlfilename("x-pull-data"), "wb")
68
pull_file.write("%s\n%s\n" % (location, rev_id))
70
def get_pull_data(br):
72
>>> br = temp_branch()
75
>>> set_pull_data(br, 'http://somewhere', '888-777')
77
('http://somewhere', '888-777')
80
filename = br.controlfilename("x-pull-data")
81
if not os.path.exists(filename):
83
pull_file = file (filename, "rb")
84
location, rev_id = [f.rstrip('\n') for f in pull_file]
85
return location, rev_id
87
def set_push_data(br, location):
88
push_file = file (br.controlfilename("x-push-data"), "wb")
89
push_file.write("%s\n" % location)
91
def get_push_data(br):
93
>>> br = temp_branch()
94
>>> get_push_data(br) is None
96
>>> set_push_data(br, 'http://somewhere')
101
filename = br.controlfilename("x-push-data")
102
if not os.path.exists(filename):
104
push_file = file (filename, "rb")
105
(location,) = [f.rstrip('\n') for f in push_file]
109
>>> shell_escape('hello')
112
def shell_escape(arg):
113
return "".join(['\\'+c for c in arg])
115
def safe_system(args):
117
>>> real_system = os.system
118
>>> os.system = sys.stdout.write
119
>>> safe_system(['a', 'b', 'cd'])
121
>>> os.system = real_system
123
arg_str = " ".join([shell_escape(a) for a in args])
124
return os.system(arg_str)
126
def rsync(source, target, ssh=False, excludes=()):
128
>>> real_system = os.system
129
>>> os.system = sys.stdout.write
131
['rsync', '-av', '--delete', 'a', 'b']
132
>>> rsync("a", "b", excludes=("*.py",))
133
['rsync', '-av', '--delete', '--exclude-from', '-', 'a', 'b']
134
>>> os.system = real_system
136
cmd = ["rsync", "-av", "--delete"]
138
cmd.extend(('-e', 'ssh'))
139
if len(excludes) > 0:
140
cmd.extend(('--exclude-from', '-'))
141
cmd.extend((source, target))
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
def push(cur_branch, location=None):
152
push_location = get_push_data(cur_branch)
153
if location is not None:
154
if not location.endswith('/'):
156
push_location = location
158
if push_location is None:
159
print "No push location saved. Please specify one on the command line."
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)
169
print "Pushing to %s" % push_location
170
rsync(cur_branch.base+'/', push_location, ssh=True, excludes=non_source)
172
set_push_data(cur_branch, push_location)
19
from bzrlib import urlutils
20
from bzrlib.errors import (
25
from bzrlib.bzrdir import BzrDir
26
from bzrlib.transport import get_transport
29
def short_committer(committer):
30
new_committer = re.sub('<.*>', '', committer).strip(' ')
31
if len(new_committer) < 2:
37
"""Screen-scrape Apache listings"""
38
apache_dir = '<img border="0" src="/icons/folder.gif" alt="[dir]">'\
41
t._remote_path = lambda x: t.base
46
expr = re.compile('<a[^>]*href="([^>]*)\/"[^>]*>', flags=re.I)
48
match = expr.search(line)
52
if url.startswith('http://') or url.startswith('/') or '../' in url:
60
def is_inside(branch):
61
return bool(branch.base.startswith(t.base))
63
if t.base.startswith('http://'):
66
branch = bzrdir.open_branch()
71
except NotBranchError:
73
return [b for b in BzrDir.find_bzrdirs(t, list_current=apache_ls,
74
evaluate=evaluate) if b is not None]
75
elif not t.listable():
76
raise BzrCommandError("Can't list this type of location.")
77
return [b for b in BzrDir.find_branches(t) if is_inside(b)]
80
def evaluate_branch_tree(bzrdir):
82
tree, branch = bzrdir._get_tree_branch()
83
except NotBranchError:
86
return True, (branch, tree)
89
def iter_branch_tree(t, lister=None):
90
return (x for x in BzrDir.find_bzrdirs(t, evaluate=evaluate_branch_tree,
91
list_current=lister) if x is not None)
94
def open_from_url(location):
95
location = urlutils.normalize_url(location)
96
dirname, basename = urlutils.split(location)
97
if location.endswith('/') and not basename.endswith('/'):
99
return get_transport(dirname).get(basename)