~abentley/bzrtools/bzrtools.dev

« back to all changes in this revision

Viewing changes to bzrtools.py

MergeĀ fromĀ ab-baz2bzr

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
17
 
import bzrlib
18
 
import bzrlib.errors
 
17
import codecs
 
18
import errno
19
19
import os
20
 
import os.path
21
 
import sys
 
20
import re
22
21
import tempfile
23
22
import shutil
24
 
import errno
25
23
from subprocess import Popen, PIPE
26
 
import codecs
27
 
import re
28
 
 
29
 
def temp_branch():
 
24
import sys
 
25
 
 
26
import bzrlib
 
27
import bzrlib.errors
 
28
from bzrlib.errors import BzrCommandError
 
29
from bzrlib.bzrdir import BzrDir
 
30
 
 
31
def temp_tree():
30
32
    dirname = tempfile.mkdtemp("temp-branch")
31
 
    return bzrlib.branch.Branch.initialize(dirname)
32
 
 
33
 
def rm_branch(br):
34
 
    shutil.rmtree(br.base)
35
 
 
36
 
def is_clean(cur_branch):
 
33
    return BzrDir.create_standalone_workingtree(dirname)
 
34
 
 
35
def rm_tree(tree):
 
36
    shutil.rmtree(tree.basedir)
 
37
 
 
38
def is_clean(cur_tree):
37
39
    """
38
40
    Return true if no files are modifed or unknown
39
41
    >>> import bzrlib.add
40
 
    >>> br = temp_branch()
41
 
    >>> is_clean(br)
 
42
    >>> tree = temp_tree()
 
43
    >>> is_clean(tree)
42
44
    (True, [])
43
 
    >>> fooname = os.path.join(br.base, "foo")
 
45
    >>> fooname = os.path.join(tree.basedir, "foo")
44
46
    >>> file(fooname, "wb").write("bar")
45
 
    >>> is_clean(br)
 
47
    >>> is_clean(tree)
46
48
    (True, [u'foo'])
47
 
    >>> br.working_tree().add(["foo"])
48
 
    >>> is_clean(br)
 
49
    >>> bzrlib.add.smart_add_tree(tree, [tree.basedir])
 
50
    ([u'foo'], {})
 
51
    >>> is_clean(tree)
49
52
    (False, [])
50
 
    >>> br.working_tree().commit("added file")
51
 
    >>> is_clean(br)
 
53
    >>> tree.commit("added file")
 
54
    >>> is_clean(tree)
52
55
    (True, [])
53
 
    >>> rm_branch(br)
 
56
    >>> rm_tree(tree)
54
57
    """
55
58
    from bzrlib.diff import compare_trees
56
 
    old_tree = cur_branch.basis_tree()
57
 
    new_tree = cur_branch.working_tree()
 
59
    old_tree = cur_tree.basis_tree()
 
60
    new_tree = cur_tree
58
61
    non_source = []
59
62
    for path, file_class, kind, file_id, entry in new_tree.list_files():
60
63
        if file_class in ('?', 'I'):
62
65
    delta = compare_trees(old_tree, new_tree, want_unchanged=False)
63
66
    return not delta.has_changed(), non_source
64
67
 
65
 
def set_pull_data(br, location, rev_id):
66
 
    pull_file = file (br.control_files.controlfilename("x-pull-data"), "wb")
67
 
    pull_file.write("%s\n%s\n" % (location, rev_id))
68
 
 
69
 
def get_pull_data(br):
70
 
    """
71
 
    >>> br = temp_branch()
72
 
    >>> get_pull_data(br)
73
 
    (None, None)
74
 
    >>> set_pull_data(br, 'http://somewhere', '888-777')
75
 
    >>> get_pull_data(br)
76
 
    ('http://somewhere', '888-777')
77
 
    >>> rm_branch(br)
78
 
    """
79
 
    filename = br.control_files.controlfilename("x-pull-data")
80
 
    if not os.path.exists(filename):
81
 
        return (None, None)
82
 
    pull_file = file (filename, "rb")
83
 
    location, rev_id = [f.rstrip('\n') for f in pull_file]
84
 
    return location, rev_id
85
 
 
86
 
def set_push_data(br, location):
87
 
    push_file = file (br.control_files.controlfilename("x-push-data"), "wb")
 
68
def set_push_data(tree, location):
 
69
    push_file = file (tree._control_files.controlfilename("x-push-data"), "wb")
88
70
    push_file.write("%s\n" % location)
89
71
 
90
 
def get_push_data(br):
 
72
def get_push_data(tree):
91
73
    """
92
 
    >>> br = temp_branch()
93
 
    >>> get_push_data(br) is None
 
74
    >>> tree = temp_tree()
 
75
    >>> get_push_data(tree) is None
94
76
    True
95
 
    >>> set_push_data(br, 'http://somewhere')
96
 
    >>> get_push_data(br)
 
77
    >>> set_push_data(tree, 'http://somewhere')
 
78
    >>> get_push_data(tree)
97
79
    'http://somewhere'
98
 
    >>> rm_branch(br)
 
80
    >>> rm_tree(tree)
99
81
    """
100
 
    filename = br.control_files.controlfilename("x-push-data")
 
82
    filename = tree._control_files.controlfilename("x-push-data")
101
83
    if not os.path.exists(filename):
102
84
        return None
103
85
    push_file = file (filename, "rb")
133
115
def rsync(source, target, ssh=False, excludes=(), silent=False, 
134
116
          rsync_name="rsync"):
135
117
    """
136
 
    >>> tempdir = tempfile.mkdtemp()
137
 
    >>> rsync(tempdir + "/a", tempdir + "/b", silent=True) #doctest: +ELLIPSIS
 
118
    >>> new_dir = tempfile.mkdtemp()
 
119
    >>> old_dir = os.getcwd()
 
120
    >>> os.chdir(new_dir)
 
121
    >>> rsync("a", "b", silent=True)
138
122
    Traceback (most recent call last):
139
123
    RsyncNoFile: No such file...
140
124
    >>> rsync(tempdir + "/a", tempdir + "/b", excludes=("*.py",), silent=True) #doctest: +ELLIPSIS
143
127
    >>> rsync(tempdir + "/a", tempdir + "/b", excludes=("*.py",), silent=True, rsync_name="rsyncc")
144
128
    Traceback (most recent call last):
145
129
    NoRsync: rsyncc not found.
146
 
    >>> os.rmdir(tempdir)
 
130
    >>> os.chdir(old_dir)
 
131
    >>> os.rmdir(new_dir)
147
132
    """
148
133
    cmd = [rsync_name, "-av", "--delete"]
149
134
    if ssh:
249
234
    except RsyncNoFile:
250
235
        return True
251
236
 
252
 
def push(cur_branch, location=None, overwrite=False):
253
 
    push_location = get_push_data(cur_branch)
 
237
def push(tree, location=None, overwrite=False, working_tree=True):
 
238
    push_location = get_push_data(tree)
254
239
    if location is not None:
255
240
        if not location.endswith('/'):
256
241
            location += '/'
257
242
        push_location = location
258
243
    
259
244
    if push_location is None:
260
 
        raise bzrlib.errors.MustUseDecorated
 
245
        if tree.branch.get_push_location() is None:
 
246
            raise BzrCommandError("No push location known or specified.")
 
247
        else:
 
248
            raise bzrlib.errors.MustUseDecorated
261
249
 
262
250
    if push_location.find('://') != -1:
263
251
        raise bzrlib.errors.MustUseDecorated
265
253
    if push_location.find(':') == -1:
266
254
        raise bzrlib.errors.MustUseDecorated
267
255
 
268
 
    clean, non_source = is_clean(cur_branch)
 
256
    clean, non_source = is_clean(tree)
269
257
    if not clean:
270
258
        print """Error: This tree has uncommitted changes or unknown (?) files.
271
259
Use "bzr status" to list them."""
272
260
        sys.exit(1)
273
 
    non_source.extend(exclusions)
 
261
    if working_tree:
 
262
        final_exclusions = non_source[:]
 
263
    else:
 
264
        wt = tree
 
265
        final_exclusions = []
 
266
        for path, status, kind, file_id, entry in wt.list_files():
 
267
            final_exclusions.append(path)
 
268
 
 
269
    final_exclusions.extend(exclusions)
274
270
    if not overwrite:
275
271
        try:
276
 
            if not history_subset(push_location, cur_branch):
 
272
            if not history_subset(push_location, tree.branch):
277
273
                raise bzrlib.errors.BzrCommandError("Local branch is not a"
278
274
                                                    " newer version of remote"
279
275
                                                    " branch.")
287
283
                " specified location.  Please ensure that"
288
284
                ' "%s" is of the form "machine:/path".' % push_location)
289
285
    print "Pushing to %s" % push_location
290
 
    rsync(cur_branch.base+'/', push_location, ssh=True, excludes=non_source)
 
286
    rsync(tree.basedir+'/', push_location, ssh=True, 
 
287
          excludes=final_exclusions)
291
288
 
292
 
    set_push_data(cur_branch, push_location)
 
289
    set_push_data(tree, push_location)
293
290
 
294
291
 
295
292
def short_committer(committer):