~abentley/bzrtools/bzrtools.dev

« back to all changes in this revision

Viewing changes to bzrtools.py

  • Committer: Aaron Bentley
  • Date: 2006-03-18 17:14:51 UTC
  • mfrom: (0.1.98 shelf)
  • Revision ID: aaron.bentley@utoronto.ca-20060318171451-2b15a9bcf7b77d69
Merge from shelf

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
 
 
28
 
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():
29
32
    dirname = tempfile.mkdtemp("temp-branch")
30
 
    return bzrlib.branch.Branch.initialize(dirname)
31
 
 
32
 
def rm_branch(br):
33
 
    shutil.rmtree(br.base)
34
 
 
35
 
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):
36
39
    """
37
40
    Return true if no files are modifed or unknown
38
41
    >>> import bzrlib.add
39
 
    >>> br = temp_branch()
40
 
    >>> is_clean(br)
 
42
    >>> tree = temp_tree()
 
43
    >>> is_clean(tree)
41
44
    (True, [])
42
 
    >>> fooname = os.path.join(br.base, "foo")
 
45
    >>> fooname = os.path.join(tree.basedir, "foo")
43
46
    >>> file(fooname, "wb").write("bar")
44
 
    >>> is_clean(br)
 
47
    >>> is_clean(tree)
45
48
    (True, [u'foo'])
46
 
    >>> br.working_tree().add(["foo"])
47
 
    >>> is_clean(br)
 
49
    >>> bzrlib.add.smart_add_tree(tree, [tree.basedir])
 
50
    ([u'foo'], {})
 
51
    >>> is_clean(tree)
48
52
    (False, [])
49
 
    >>> br.working_tree().commit("added file")
50
 
    >>> is_clean(br)
 
53
    >>> tree.commit("added file")
 
54
    >>> is_clean(tree)
51
55
    (True, [])
52
 
    >>> rm_branch(br)
 
56
    >>> rm_tree(tree)
53
57
    """
54
58
    from bzrlib.diff import compare_trees
55
 
    old_tree = cur_branch.basis_tree()
56
 
    new_tree = cur_branch.working_tree()
 
59
    old_tree = cur_tree.basis_tree()
 
60
    new_tree = cur_tree
57
61
    non_source = []
58
62
    for path, file_class, kind, file_id, entry in new_tree.list_files():
59
63
        if file_class in ('?', 'I'):
61
65
    delta = compare_trees(old_tree, new_tree, want_unchanged=False)
62
66
    return not delta.has_changed(), non_source
63
67
 
64
 
def set_pull_data(br, location, rev_id):
65
 
    pull_file = file (br.controlfilename("x-pull-data"), "wb")
66
 
    pull_file.write("%s\n%s\n" % (location, rev_id))
67
 
 
68
 
def get_pull_data(br):
69
 
    """
70
 
    >>> br = temp_branch()
71
 
    >>> get_pull_data(br)
72
 
    (None, None)
73
 
    >>> set_pull_data(br, 'http://somewhere', '888-777')
74
 
    >>> get_pull_data(br)
75
 
    ('http://somewhere', '888-777')
76
 
    >>> rm_branch(br)
77
 
    """
78
 
    filename = br.controlfilename("x-pull-data")
79
 
    if not os.path.exists(filename):
80
 
        return (None, None)
81
 
    pull_file = file (filename, "rb")
82
 
    location, rev_id = [f.rstrip('\n') for f in pull_file]
83
 
    return location, rev_id
84
 
 
85
 
def set_push_data(br, location):
86
 
    push_file = file (br.controlfilename("x-push-data"), "wb")
 
68
def set_push_data(tree, location):
 
69
    push_file = file (tree.branch.control_files.controlfilename("x-push-data"), "wb")
87
70
    push_file.write("%s\n" % location)
88
71
 
89
 
def get_push_data(br):
 
72
def get_push_data(tree):
90
73
    """
91
 
    >>> br = temp_branch()
92
 
    >>> get_push_data(br) is None
 
74
    >>> tree = temp_tree()
 
75
    >>> get_push_data(tree) is None
93
76
    True
94
 
    >>> set_push_data(br, 'http://somewhere')
95
 
    >>> get_push_data(br)
 
77
    >>> set_push_data(tree, 'http://somewhere')
 
78
    >>> get_push_data(tree)
96
79
    'http://somewhere'
97
 
    >>> rm_branch(br)
 
80
    >>> rm_tree(tree)
98
81
    """
99
 
    filename = br.controlfilename("x-push-data")
 
82
    filename = tree.branch.control_files.controlfilename("x-push-data")
100
83
    if not os.path.exists(filename):
101
84
        return None
102
85
    push_file = file (filename, "rb")
132
115
def rsync(source, target, ssh=False, excludes=(), silent=False, 
133
116
          rsync_name="rsync"):
134
117
    """
 
118
    >>> new_dir = tempfile.mkdtemp()
 
119
    >>> old_dir = os.getcwd()
 
120
    >>> os.chdir(new_dir)
135
121
    >>> rsync("a", "b", silent=True)
136
122
    Traceback (most recent call last):
137
 
    RsyncNoFile: No such file a
138
 
    >>> rsync("a", "b", excludes=("*.py",), silent=True)
 
123
    RsyncNoFile: No such file...
 
124
    >>> rsync(new_dir + "/a", new_dir + "/b", excludes=("*.py",), silent=True)
139
125
    Traceback (most recent call last):
140
 
    RsyncNoFile: No such file a
141
 
    >>> rsync("a", "b", excludes=("*.py",), silent=True, rsync_name="rsyncc")
 
126
    RsyncNoFile: No such file...
 
127
    >>> rsync(new_dir + "/a", new_dir + "/b", excludes=("*.py",), silent=True, rsync_name="rsyncc")
142
128
    Traceback (most recent call last):
143
129
    NoRsync: rsyncc not found.
 
130
    >>> os.chdir(old_dir)
 
131
    >>> os.rmdir(new_dir)
144
132
    """
145
133
    cmd = [rsync_name, "-av", "--delete"]
146
134
    if ssh:
201
189
        raise RsyncUnknownStatus(proc.returncode)
202
190
    return [l.split(' ')[-1].rstrip('\n') for l in result.splitlines(True)]
203
191
 
204
 
exclusions = ('.bzr/x-push-data', '.bzr/parent', '.bzr/x-pull-data', 
205
 
              '.bzr/x-pull', '.bzr/pull', '.bzr/stat-cache',
206
 
              '.bzr/x-rsync-data')
 
192
exclusions = ('.bzr/x-push-data', '.bzr/branch/x-push/data', '.bzr/parent', 
 
193
              '.bzr/branch/parent', '.bzr/x-pull-data', '.bzr/x-pull',
 
194
              '.bzr/pull', '.bzr/stat-cache', '.bzr/x-rsync-data',
 
195
              '.bzr/basis-inventory', '.bzr/inventory.backup.weave')
207
196
 
208
197
 
209
198
def read_revision_history(fname):
222
211
    tempdir = tempfile.mkdtemp('push')
223
212
    try:
224
213
        history_fname = os.path.join(tempdir, 'revision-history')
225
 
        cmd = rsync(location+'.bzr/revision-history', history_fname,
226
 
                    silent=True)
 
214
        try:
 
215
            cmd = rsync(location+'.bzr/revision-history', history_fname,
 
216
                        silent=True)
 
217
        except RsyncNoFile:
 
218
            cmd = rsync(location+'.bzr/branch/revision-history', history_fname,
 
219
                        silent=True)
227
220
        history = read_revision_history(history_fname)
228
221
    finally:
229
222
        shutil.rmtree(tempdir)
246
239
    except RsyncNoFile:
247
240
        return True
248
241
 
249
 
def push(cur_branch, location=None, overwrite=False):
250
 
    push_location = get_push_data(cur_branch)
 
242
def push(tree, location=None, overwrite=False, working_tree=True):
 
243
    push_location = get_push_data(tree)
251
244
    if location is not None:
252
245
        if not location.endswith('/'):
253
246
            location += '/'
254
247
        push_location = location
255
248
    
256
249
    if push_location is None:
257
 
        raise bzrlib.errors.MustUseDecorated
 
250
        if tree.branch.get_push_location() is None:
 
251
            raise BzrCommandError("No push location known or specified.")
 
252
        else:
 
253
            raise bzrlib.errors.MustUseDecorated
258
254
 
259
255
    if push_location.find('://') != -1:
260
256
        raise bzrlib.errors.MustUseDecorated
262
258
    if push_location.find(':') == -1:
263
259
        raise bzrlib.errors.MustUseDecorated
264
260
 
265
 
    clean, non_source = is_clean(cur_branch)
266
 
    if not clean:
267
 
        print """Error: This tree has uncommitted changes or unknown (?) files.
268
 
Use "bzr status" to list them."""
269
 
        sys.exit(1)
270
 
    non_source.extend(exclusions)
 
261
    if working_tree:
 
262
        clean, non_source = is_clean(tree)
 
263
        if not clean:
 
264
            print """Error: This tree has uncommitted changes or unknown (?) files.
 
265
    Use "bzr status" to list them."""
 
266
            sys.exit(1)
 
267
        final_exclusions = non_source[:]
 
268
    else:
 
269
        wt = tree
 
270
        final_exclusions = []
 
271
        for path, status, kind, file_id, entry in wt.list_files():
 
272
            final_exclusions.append(path)
 
273
 
 
274
    final_exclusions.extend(exclusions)
271
275
    if not overwrite:
272
276
        try:
273
 
            if not history_subset(push_location, cur_branch):
 
277
            if not history_subset(push_location, tree.branch):
274
278
                raise bzrlib.errors.BzrCommandError("Local branch is not a"
275
279
                                                    " newer version of remote"
276
280
                                                    " branch.")
284
288
                " specified location.  Please ensure that"
285
289
                ' "%s" is of the form "machine:/path".' % push_location)
286
290
    print "Pushing to %s" % push_location
287
 
    rsync(cur_branch.base+'/', push_location, ssh=True, excludes=non_source)
288
 
 
289
 
    set_push_data(cur_branch, push_location)
 
291
    rsync(tree.basedir+'/', push_location, ssh=True, 
 
292
          excludes=final_exclusions)
 
293
 
 
294
    set_push_data(tree, push_location)
 
295
 
 
296
 
 
297
def short_committer(committer):
 
298
    new_committer = re.sub('<.*>', '', committer).strip(' ')
 
299
    if len(new_committer) < 2:
 
300
        return committer
 
301
    return new_committer
 
302
 
290
303
 
291
304
def run_tests():
292
305
    import doctest