~phanatic/olive/main

« back to all changes in this revision

Viewing changes to olive/backend/info.py

  • Committer: Szilveszter Farkas (Phanatic)
  • Date: 2006-09-27 19:11:59 UTC
  • mfrom: (82.1.8 merge)
  • Revision ID: Szilveszter.Farkas@gmail.com-20060927191159-cc4e54f613575779
Merge all changes. Release 0.11.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006 by Szilveszter Farkas (Phanatic) <szilveszter.farkas@gmail.com>
2
 
# Some parts of the code are:
3
 
# Copyright (C) 2005, 2006 by Canonical Ltd
4
 
#
5
 
# This program is free software; you can redistribute it and/or modify
6
 
# it under the terms of the GNU General Public License as published by
7
 
# the Free Software Foundation; either version 2 of the License, or
8
 
# (at your option) any later version.
9
 
#
10
 
# This program is distributed in the hope that it will be useful,
11
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
# GNU General Public License for more details.
14
 
#
15
 
# You should have received a copy of the GNU General Public License
16
 
# along with this program; if not, write to the Free Software
17
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 
 
19
 
import bzrlib
20
 
import bzrlib.errors as errors
21
 
 
22
 
from bzrlib.branch import Branch
23
 
from bzrlib.workingtree import WorkingTree
24
 
 
25
 
from errors import (DifferentBranchesError, NotBranchError, PermissionDenied,
26
 
                    PrefixFormatError, RevisionValueError)
27
 
 
28
 
def diff(revision=None, file_list=None, diff_options=None, prefix=None):
29
 
    """ Save the diff into a temporary file.
30
 
    
31
 
    :param revision: a list of revision numbers (one or two elements)
32
 
    
33
 
    :param file_list: list of files you want to diff
34
 
    
35
 
    :param diff_options: external diff options
36
 
    
37
 
    :param prefix: 0 - p0, 1 - p1, or specify prefixes in the form of old/:new/
38
 
    
39
 
    :return: path to the temporary file which contains the diff output (the frontend has to remove it!)
40
 
    """
41
 
    from tempfile import mkstemp
42
 
    
43
 
    from bzrlib.builtins import internal_tree_files
44
 
    from bzrlib.diff import show_diff_trees
45
 
    from bzrlib.revisionspec import RevisionSpec_int
46
 
    from bzrlib.workingtree import WorkingTree
47
 
    
48
 
    from info_helper import diff_helper
49
 
 
50
 
    if (prefix is None) or (prefix == '0'):
51
 
        # diff -p0 format
52
 
        old_label = ''
53
 
        new_label = ''
54
 
    elif prefix == '1':
55
 
        old_label = 'old/'
56
 
        new_label = 'new/'
57
 
    else:
58
 
        if not ':' in prefix:
59
 
            raise PrefixFormatError
60
 
        old_label, new_label = prefix.split(":")
61
 
    
62
 
    try:
63
 
        tree1, file_list = internal_tree_files(file_list)
64
 
        tree2 = None
65
 
        b = None
66
 
        b2 = None
67
 
    except errors.FileInWrongBranch:
68
 
        if len(file_list) != 2:
69
 
            raise DifferentBranchesError
70
 
 
71
 
        tree1, file1 = WorkingTree.open_containing(file_list[0])
72
 
        tree2, file2 = WorkingTree.open_containing(file_list[1])
73
 
    
74
 
        if file1 != "" or file2 != "":
75
 
            raise DifferentBranchesError
76
 
    
77
 
        file_list = None
78
 
    
79
 
    tmpfile = mkstemp(prefix='olive_')
80
 
    tmpfp = open(tmpfile[1], 'w')
81
 
    
82
 
    if revision is not None:
83
 
        if tree2 is not None:
84
 
            raise RevisionValueError
85
 
    
86
 
        if len(revision) >= 1:
87
 
            revision[0] = RevisionSpec_int(revision[0])
88
 
        if len(revision) == 2:
89
 
            revision[1] = RevisionSpec_int(revision[1])
90
 
        
91
 
        if (len(revision) == 1) or (revision[1].spec is None):
92
 
            ret = diff_helper(tree1, file_list, diff_options,
93
 
                              revision[0], 
94
 
                              old_label=old_label, new_label=new_label,
95
 
                              output=tmpfp)
96
 
        elif len(revision) == 2:
97
 
            ret = diff_helper(tree1, file_list, diff_options,
98
 
                              revision[0], revision[1],
99
 
                              old_label=old_label, new_label=new_label,
100
 
                              output=tmpfp)
101
 
        else:
102
 
            raise RevisionValueError
103
 
    else:
104
 
        if tree2 is not None:
105
 
            ret = show_diff_trees(tree1, tree2, tmpfp, 
106
 
                                  specific_files=file_list,
107
 
                                  external_diff_options=diff_options,
108
 
                                  old_label=old_label, new_label=new_label)
109
 
        else:
110
 
            ret = diff_helper(tree1, file_list, diff_options,
111
 
                              old_label=old_label, new_label=new_label,
112
 
                              output=tmpfp)
113
 
    
114
 
    tmpfp.close()
115
 
    
116
 
    if ret == 0:
117
 
        return False
118
 
    else:
119
 
        return tmpfile[1]
120
 
 
121
 
def get_push_location(location):
122
 
    """ Get the stored push location of a branch.
123
 
    
124
 
    :param location: the path to the branch
125
 
    
126
 
    :return: the stored location
127
 
    """
128
 
    from bzrlib.branch import Branch
129
 
    
130
 
    try:
131
 
        branch = Branch.open_containing(location)[0]
132
 
    except errors.NotBranchError:
133
 
        raise NotBranchError(location)
134
 
    except:
135
 
        raise
136
 
    
137
 
    return branch.get_push_location()
138
 
 
139
 
def info(location):
140
 
    """ Get info about branch, working tree, and repository
141
 
    
142
 
    :param location: the location of the branch/working tree/repository
143
 
    
144
 
    :return: the information in dictionary format
145
 
    
146
 
    The following informations are delivered (if available):
147
 
    ret['location']['lightcoroot']: Light checkout root
148
 
    ret['location']['sharedrepo']: Shared repository
149
 
    ret['location']['repobranch']: Repository branch
150
 
    ret['location']['cobranch']: Checkout of branch
151
 
    ret['location']['repoco']: Repository checkout
152
 
    ret['location']['coroot']: Checkout root
153
 
    ret['location']['branchroot']: Branch root
154
 
    ret['related']['parentbranch']: Parent branch
155
 
    ret['related']['publishbranch']: Publish to branch
156
 
    ret['format']['control']: Control format
157
 
    ret['format']['workingtree']: Working tree format
158
 
    ret['format']['branch']: Branch format
159
 
    ret['format']['repository']: Repository format
160
 
    ret['locking']['workingtree']: Working tree lock status
161
 
    ret['locking']['branch']: Branch lock status
162
 
    ret['locking']['repository']: Repository lock status
163
 
    ret['missing']['branch']: Missing revisions in branch
164
 
    ret['missing']['workingtree']: Missing revisions in working tree
165
 
    ret['wtstats']['unchanged']: Unchanged files
166
 
    ret['wtstats']['modified']: Modified files
167
 
    ret['wtstats']['added']: Added files
168
 
    ret['wtstats']['removed']: Removed files
169
 
    ret['wtstats']['renamed']: Renamed files
170
 
    ret['wtstats']['unknown']: Unknown files
171
 
    ret['wtstats']['ignored']: Ingnored files
172
 
    ret['wtstats']['subdirs']: Versioned subdirectories
173
 
    ret['brstats']['revno']: Revisions in branch
174
 
    ret['brstats']['commiters']: Number of commiters
175
 
    ret['brstats']['age']: Age of branch in days
176
 
    ret['brstats']['firstrev']: Time of first revision
177
 
    ret['brstats']['lastrev']: Time of last revision
178
 
    ret['repstats']['revisions']: Revisions in repository
179
 
    ret['repstats']['size']: Size of repository in bytes
180
 
    """
181
 
    import bzrlib.bzrdir as bzrdir
182
 
    
183
 
    import info_helper
184
 
    
185
 
    ret = {}
186
 
    try:
187
 
        a_bzrdir = bzrdir.BzrDir.open_containing(location)[0]
188
 
    except errors.NotBranchError:
189
 
        raise NotBranchError(location)
190
 
 
191
 
    try:
192
 
        working = a_bzrdir.open_workingtree()
193
 
        working.lock_read()
194
 
        try:
195
 
            branch = working.branch
196
 
            repository = branch.repository
197
 
            control = working.bzrdir
198
 
            
199
 
            ret['location'] = info_helper.get_location_info(repository, branch, working)
200
 
            ret['related'] = info_helper.get_related_info(branch)
201
 
            ret['format'] = info_helper.get_format_info(control, repository, branch, working)
202
 
            ret['locking'] = info_helper.get_locking_info(repository, branch, working)
203
 
            ret['missing'] = {}
204
 
            ret['missing']['branch'] = info_helper.get_missing_revisions_branch(branch)
205
 
            ret['missing']['workingtree'] = info_helper.get_missing_revisions_working(working)
206
 
            ret['wtstats'] = info_helper.get_working_stats(working)
207
 
            ret['brstats'] = info_helper.get_branch_stats(branch)
208
 
            ret['repstats'] = info_helper.get_repository_stats(repository)
209
 
        finally:
210
 
            working.unlock()
211
 
            return ret
212
 
        return
213
 
    except (errors.NoWorkingTree, errors.NotLocalUrl):
214
 
        pass
215
 
 
216
 
    try:
217
 
        branch = a_bzrdir.open_branch()
218
 
        branch.lock_read()
219
 
        try:
220
 
            ret['location'] = info_helper.get_location_info(repository, branch)
221
 
            ret['related'] = info_helper.get_related_info(branch)
222
 
            ret['format'] = info_helper.get_format_info(control, repository, branch)
223
 
            ret['locking'] = info_helper.get_locking_info(repository, branch)
224
 
            ret['missing']['branch'] = info_helper.get_missing_revisions_branch(branch)
225
 
            ret['brstats'] = info_helper.get_branch_stats(branch)
226
 
            ret['repstats'] = info_helper.get_repository_stats(repository)
227
 
        finally:
228
 
            branch.unlock()
229
 
            return ret
230
 
        return
231
 
    except errors.NotBranchError:
232
 
        pass
233
 
 
234
 
    try:
235
 
        repository = a_bzrdir.open_repository()
236
 
        repository.lock_read()
237
 
        try:
238
 
            ret['location'] = info_helper.get_location_info(repository)
239
 
            ret['format'] = info_helper.get_format_info(control, repository)
240
 
            ret['locking'] = info_helper.get_locking_info(repository)
241
 
            ret['repstats'] = info_helper.get_repository_stats(repository)
242
 
        finally:
243
 
            repository.unlock()
244
 
            return ret
245
 
        return
246
 
    except errors.NoRepositoryPresent:
247
 
        pass
248
 
 
249
 
def is_branch(location):
250
 
    """ Check if the location is a branch.
251
 
    
252
 
    :param location: the location you want to check
253
 
    
254
 
    :return: True or False respectively
255
 
    """
256
 
    try:
257
 
        branch = Branch.open_containing(location)[0]
258
 
    except errors.NotBranchError:
259
 
        return False
260
 
    except errors.PermissionDenied:
261
 
        raise PermissionDenied(location)
262
 
    else:
263
 
        return True
264
 
        
265
 
 
266
 
def is_checkout(location):
267
 
    """ Check if the location is a checkout.
268
 
    
269
 
    :param location: the location you want to check
270
 
    
271
 
    :return: True or False respectively
272
 
    """
273
 
    try:
274
 
        branch = Branch.open_containing(location)[0]
275
 
    except errors.NotBranchError:
276
 
        raise NotBranchError
277
 
    
278
 
    try:
279
 
        working = WorkingTree.open_containing(location)[0]
280
 
    except:
281
 
        raise
282
 
    
283
 
    working_path = working.bzrdir.root_transport.base
284
 
    branch_path = branch.bzrdir.root_transport.base
285
 
    
286
 
    if working_path != branch_path:
287
 
        # lightweight checkout
288
 
        return True
289
 
    elif branch.get_bound_location():
290
 
        # checkout
291
 
        return True
292
 
    else:
293
 
        return False
294
 
 
295
 
def log(location, timezone='original', verbose=False, show_ids=False,
296
 
        forward=False, revision=None, log_format=None, message=None,
297
 
        long=False, short=False, line=False):
298
 
    """ Print log into a temporary file.
299
 
    
300
 
    :param location: location of local/remote branch or file
301
 
    
302
 
    :param timzone: requested timezone
303
 
    
304
 
    :param verbose: verbose output
305
 
    
306
 
    :param show_ids:
307
 
    
308
 
    :param forward: if True, start from the earliest entry
309
 
    
310
 
    :param revision: revision range as a list ([from, to])
311
 
    
312
 
    :param log_format: line, short, long
313
 
    
314
 
    :param message: show revisions whose message matches this regexp
315
 
    
316
 
    :param long: long log format
317
 
    
318
 
    :param short: short log format
319
 
    
320
 
    :param line: line log format
321
 
    
322
 
    :return: full path to the temporary file containing the log (the frontend has to remove it!)
323
 
    """
324
 
    from tempfile import mkstemp
325
 
    
326
 
    from bzrlib import bzrdir    
327
 
    from bzrlib.builtins import get_log_format
328
 
    from bzrlib.log import log_formatter, show_log
329
 
    from bzrlib.revisionspec import RevisionSpec_int
330
 
    
331
 
    assert message is None or isinstance(message, basestring), \
332
 
        "invalid message argument %r" % message
333
 
    direction = (forward and 'forward') or 'reverse'
334
 
        
335
 
    # log everything
336
 
    file_id = None
337
 
    
338
 
    # find the file id to log:
339
 
    dir, fp = bzrdir.BzrDir.open_containing(location)
340
 
    b = dir.open_branch()
341
 
    if fp != '':
342
 
        try:
343
 
            # might be a tree:
344
 
            inv = dir.open_workingtree().inventory
345
 
        except (errors.NotBranchError, errors.NotLocalUrl):
346
 
            # either no tree, or is remote.
347
 
            inv = b.basis_tree().inventory
348
 
        file_id = inv.path2id(fp)
349
 
 
350
 
    if revision is not None:
351
 
        if len(revision) >= 1:
352
 
            revision[0] = RevisionSpec_int(revision[0])
353
 
        if len(revision) == 2:
354
 
            revision[1] = RevisionSpec_int(revision[1])
355
 
    
356
 
    if revision is None:
357
 
        rev1 = None
358
 
        rev2 = None
359
 
    elif len(revision) == 1:
360
 
        rev1 = rev2 = revision[0].in_history(b).revno
361
 
    elif len(revision) == 2:
362
 
        if revision[0].spec is None:
363
 
            # missing begin-range means first revision
364
 
            rev1 = 1
365
 
        else:
366
 
            rev1 = revision[0].in_history(b).revno
367
 
 
368
 
        if revision[1].spec is None:
369
 
            # missing end-range means last known revision
370
 
            rev2 = b.revno()
371
 
        else:
372
 
            rev2 = revision[1].in_history(b).revno
373
 
    else:
374
 
        raise RevisionValueError
375
 
 
376
 
    # By this point, the revision numbers are converted to the +ve
377
 
    # form if they were supplied in the -ve form, so we can do
378
 
    # this comparison in relative safety
379
 
    if rev1 > rev2:
380
 
        (rev2, rev1) = (rev1, rev2)
381
 
 
382
 
    if (log_format == None):
383
 
        default = b.get_config().log_format()
384
 
        log_format = get_log_format(long=long, short=short, line=line, 
385
 
                                    default=default)
386
 
    
387
 
    tmpfile = mkstemp(prefix='olive_')
388
 
    tmpfp = open(tmpfile[1], 'w')
389
 
    
390
 
    lf = log_formatter(log_format,
391
 
                       show_ids=show_ids,
392
 
                       to_file=tmpfp,
393
 
                       show_timezone=timezone)
394
 
 
395
 
    show_log(b,
396
 
             lf,
397
 
             file_id,
398
 
             verbose=verbose,
399
 
             direction=direction,
400
 
             start_revision=rev1,
401
 
             end_revision=rev2,
402
 
             search=message)
403
 
    
404
 
    tmpfp.close()
405
 
    return tmpfile[1]
406
 
 
407
 
def nick(branch, nickname=None):
408
 
    """ Get or set nickname.
409
 
    
410
 
    :param branch: path to the branch
411
 
    
412
 
    :param nickname: if specified, the nickname will be set
413
 
    
414
 
    :return: nickname
415
 
    """
416
 
    try:
417
 
        branch = Branch.open_containing(branch)[0]
418
 
    except errors.NotBranchError:
419
 
        raise NotBranchError
420
 
    
421
 
    if nickname is not None:
422
 
        branch.nick = nickname
423
 
 
424
 
    return branch.nick    
425
 
 
426
 
def revno(branch):
427
 
    """ Get current revision number for specified branch
428
 
    
429
 
    :param branch: path to the branch
430
 
    
431
 
    :return: revision number
432
 
    """
433
 
    try:
434
 
        revno = Branch.open_containing(branch)[0].revno()
435
 
    except errors.NotBranchError:
436
 
        raise NotBranchError
437
 
    else:
438
 
        return revno
439
 
 
440
 
def version():
441
 
    """ Get version information from bzr
442
 
    
443
 
    :return: bzrlib version
444
 
    """
445
 
    return bzrlib.__version__
446
 
 
447
 
def whoami(branch=None, email=False):
448
 
    """ Get user's data (name and email address)
449
 
    
450
 
    :param branch: if specified, the user's data will be looked up in the branch's config
451
 
    
452
 
    :param email: if True, only the email address will be returned
453
 
    
454
 
    :return: user info (only email address if email is True)
455
 
    """
456
 
    from bzrlib.workingtree import WorkingTree
457
 
    
458
 
    if branch is not None:
459
 
        try:
460
 
            b = WorkingTree.open_containing(u'.')[0].branch
461
 
            config = bzrlib.config.BranchConfig(b)
462
 
        except NotBranchError:
463
 
            config = bzrlib.config.GlobalConfig()
464
 
    else:
465
 
        config = bzrlib.config.GlobalConfig()
466
 
        
467
 
    if email:
468
 
        return config.user_email()
469
 
    else:
470
 
        return config.username()