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
 
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.
 
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.
 
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
 
20
 
import bzrlib.errors as errors
 
22
 
from bzrlib.branch import Branch
 
23
 
from bzrlib.workingtree import WorkingTree
 
25
 
from errors import (DifferentBranchesError, NotBranchError, PermissionDenied,
 
26
 
                    PrefixFormatError, RevisionValueError)
 
28
 
def diff(revision=None, file_list=None, diff_options=None, prefix=None):
 
29
 
    """ Save the diff into a temporary file.
 
31
 
    :param revision: a list of revision numbers (one or two elements)
 
33
 
    :param file_list: list of files you want to diff
 
35
 
    :param diff_options: external diff options
 
37
 
    :param prefix: 0 - p0, 1 - p1, or specify prefixes in the form of old/:new/
 
39
 
    :return: path to the temporary file which contains the diff output (the frontend has to remove it!)
 
41
 
    from tempfile import mkstemp
 
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
 
48
 
    from info_helper import diff_helper
 
50
 
    if (prefix is None) or (prefix == '0'):
 
59
 
            raise PrefixFormatError
 
60
 
        old_label, new_label = prefix.split(":")
 
63
 
        tree1, file_list = internal_tree_files(file_list)
 
67
 
    except errors.FileInWrongBranch:
 
68
 
        if len(file_list) != 2:
 
69
 
            raise DifferentBranchesError
 
71
 
        tree1, file1 = WorkingTree.open_containing(file_list[0])
 
72
 
        tree2, file2 = WorkingTree.open_containing(file_list[1])
 
74
 
        if file1 != "" or file2 != "":
 
75
 
            raise DifferentBranchesError
 
79
 
    tmpfile = mkstemp(prefix='olive_')
 
80
 
    tmpfp = open(tmpfile[1], 'w')
 
82
 
    if revision is not None:
 
84
 
            raise RevisionValueError
 
86
 
        if len(revision) >= 1:
 
87
 
            revision[0] = RevisionSpec_int(revision[0])
 
88
 
        if len(revision) == 2:
 
89
 
            revision[1] = RevisionSpec_int(revision[1])
 
91
 
        if (len(revision) == 1) or (revision[1].spec is None):
 
92
 
            ret = diff_helper(tree1, file_list, diff_options,
 
94
 
                              old_label=old_label, new_label=new_label,
 
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,
 
102
 
            raise RevisionValueError
 
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)
 
110
 
            ret = diff_helper(tree1, file_list, diff_options,
 
111
 
                              old_label=old_label, new_label=new_label,
 
121
 
def get_push_location(location):
 
122
 
    """ Get the stored push location of a branch.
 
124
 
    :param location: the path to the branch
 
126
 
    :return: the stored location
 
128
 
    from bzrlib.branch import Branch
 
131
 
        branch = Branch.open_containing(location)[0]
 
132
 
    except errors.NotBranchError:
 
133
 
        raise NotBranchError(location)
 
137
 
    return branch.get_push_location()
 
140
 
    """ Get info about branch, working tree, and repository
 
142
 
    :param location: the location of the branch/working tree/repository
 
144
 
    :return: the information in dictionary format
 
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
 
181
 
    import bzrlib.bzrdir as bzrdir
 
187
 
        a_bzrdir = bzrdir.BzrDir.open_containing(location)[0]
 
188
 
    except errors.NotBranchError:
 
189
 
        raise NotBranchError(location)
 
192
 
        working = a_bzrdir.open_workingtree()
 
195
 
            branch = working.branch
 
196
 
            repository = branch.repository
 
197
 
            control = working.bzrdir
 
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)
 
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)
 
213
 
    except (errors.NoWorkingTree, errors.NotLocalUrl):
 
217
 
        branch = a_bzrdir.open_branch()
 
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)
 
231
 
    except errors.NotBranchError:
 
235
 
        repository = a_bzrdir.open_repository()
 
236
 
        repository.lock_read()
 
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)
 
246
 
    except errors.NoRepositoryPresent:
 
249
 
def is_branch(location):
 
250
 
    """ Check if the location is a branch.
 
252
 
    :param location: the location you want to check
 
254
 
    :return: True or False respectively
 
257
 
        branch = Branch.open_containing(location)[0]
 
258
 
    except errors.NotBranchError:
 
260
 
    except errors.PermissionDenied:
 
261
 
        raise PermissionDenied(location)
 
266
 
def is_checkout(location):
 
267
 
    """ Check if the location is a checkout.
 
269
 
    :param location: the location you want to check
 
271
 
    :return: True or False respectively
 
274
 
        branch = Branch.open_containing(location)[0]
 
275
 
    except errors.NotBranchError:
 
279
 
        working = WorkingTree.open_containing(location)[0]
 
283
 
    working_path = working.bzrdir.root_transport.base
 
284
 
    branch_path = branch.bzrdir.root_transport.base
 
286
 
    if working_path != branch_path:
 
287
 
        # lightweight checkout
 
289
 
    elif branch.get_bound_location():
 
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.
 
300
 
    :param location: location of local/remote branch or file
 
302
 
    :param timzone: requested timezone
 
304
 
    :param verbose: verbose output
 
308
 
    :param forward: if True, start from the earliest entry
 
310
 
    :param revision: revision range as a list ([from, to])
 
312
 
    :param log_format: line, short, long
 
314
 
    :param message: show revisions whose message matches this regexp
 
316
 
    :param long: long log format
 
318
 
    :param short: short log format
 
320
 
    :param line: line log format
 
322
 
    :return: full path to the temporary file containing the log (the frontend has to remove it!)
 
324
 
    from tempfile import mkstemp
 
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
 
331
 
    assert message is None or isinstance(message, basestring), \
 
332
 
        "invalid message argument %r" % message
 
333
 
    direction = (forward and 'forward') or 'reverse'
 
338
 
    # find the file id to log:
 
339
 
    dir, fp = bzrdir.BzrDir.open_containing(location)
 
340
 
    b = dir.open_branch()
 
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)
 
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])
 
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
 
366
 
            rev1 = revision[0].in_history(b).revno
 
368
 
        if revision[1].spec is None:
 
369
 
            # missing end-range means last known revision
 
372
 
            rev2 = revision[1].in_history(b).revno
 
374
 
        raise RevisionValueError
 
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
 
380
 
        (rev2, rev1) = (rev1, rev2)
 
382
 
    if (log_format == None):
 
383
 
        default = b.get_config().log_format()
 
384
 
        log_format = get_log_format(long=long, short=short, line=line, 
 
387
 
    tmpfile = mkstemp(prefix='olive_')
 
388
 
    tmpfp = open(tmpfile[1], 'w')
 
390
 
    lf = log_formatter(log_format,
 
393
 
                       show_timezone=timezone)
 
407
 
def nick(branch, nickname=None):
 
408
 
    """ Get or set nickname.
 
410
 
    :param branch: path to the branch
 
412
 
    :param nickname: if specified, the nickname will be set
 
417
 
        branch = Branch.open_containing(branch)[0]
 
418
 
    except errors.NotBranchError:
 
421
 
    if nickname is not None:
 
422
 
        branch.nick = nickname
 
427
 
    """ Get current revision number for specified branch
 
429
 
    :param branch: path to the branch
 
431
 
    :return: revision number
 
434
 
        revno = Branch.open_containing(branch)[0].revno()
 
435
 
    except errors.NotBranchError:
 
441
 
    """ Get version information from bzr
 
443
 
    :return: bzrlib version
 
445
 
    return bzrlib.__version__
 
447
 
def whoami(branch=None, email=False):
 
448
 
    """ Get user's data (name and email address)
 
450
 
    :param branch: if specified, the user's data will be looked up in the branch's config
 
452
 
    :param email: if True, only the email address will be returned
 
454
 
    :return: user info (only email address if email is True)
 
456
 
    from bzrlib.workingtree import WorkingTree
 
458
 
    if branch is not None:
 
460
 
            b = WorkingTree.open_containing(u'.')[0].branch
 
461
 
            config = bzrlib.config.BranchConfig(b)
 
462
 
        except NotBranchError:
 
463
 
            config = bzrlib.config.GlobalConfig()
 
465
 
        config = bzrlib.config.GlobalConfig()
 
468
 
        return config.user_email()
 
470
 
        return config.username()