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
24
from errors import (DifferentBranchesError, NotBranchError, PrefixFormatError,
27
def diff(revision=None, file_list=None, diff_options=None, prefix=None):
28
""" Save the diff into a temporary file.
30
:param revision: a list of revision numbers (one or two elements)
32
:param file_list: list of files you want to diff
34
:param diff_options: external diff options
36
:param prefix: 0 - p0, 1 - p1, or specify prefixes in the form of old/:new/
38
:return: path to the temporary file which contains the diff output (the frontend has to remove it!)
40
from tempfile import mkstemp
42
from bzrlib.builtins import internal_tree_files
43
from bzrlib.diff import show_diff_trees
44
from bzrlib.revisionspec import RevisionSpec_int
45
from bzrlib.workingtree import WorkingTree
47
from info_helper import diff_helper
49
if (prefix is None) or (prefix == '0'):
58
raise PrefixFormatError
59
old_label, new_label = prefix.split(":")
62
tree1, file_list = internal_tree_files(file_list)
66
except errors.FileInWrongBranch:
67
if len(file_list) != 2:
68
raise DifferentBranchesError
70
tree1, file1 = WorkingTree.open_containing(file_list[0])
71
tree2, file2 = WorkingTree.open_containing(file_list[1])
73
if file1 != "" or file2 != "":
74
raise DifferentBranchesError
78
tmpfile = mkstemp(prefix='olive_')
79
tmpfp = open(tmpfile[1], 'w')
81
if revision is not None:
83
raise RevisionValueError
85
if len(revision) >= 1:
86
revision[0] = RevisionSpec_int(revision[0])
87
if len(revision) == 2:
88
revision[1] = RevisionSpec_int(revision[1])
90
if (len(revision) == 1) or (revision[1].spec is None):
91
ret = diff_helper(tree1, file_list, diff_options,
93
old_label=old_label, new_label=new_label,
95
elif len(revision) == 2:
96
ret = diff_helper(tree1, file_list, diff_options,
97
revision[0], revision[1],
98
old_label=old_label, new_label=new_label,
101
raise RevisionValueError
103
if tree2 is not None:
104
ret = show_diff_trees(tree1, tree2, tmpfp,
105
specific_files=file_list,
106
external_diff_options=diff_options,
107
old_label=old_label, new_label=new_label)
109
ret = diff_helper(tree1, file_list, diff_options,
110
old_label=old_label, new_label=new_label,
121
""" Get info about branch, working tree, and repository
123
:param location: the location of the branch/working tree/repository
125
:return: the information in dictionary format
127
The following informations are delivered (if available):
128
ret['location']['lightcoroot']: Light checkout root
129
ret['location']['sharedrepo']: Shared repository
130
ret['location']['repobranch']: Repository branch
131
ret['location']['cobranch']: Checkout of branch
132
ret['location']['repoco']: Repository checkout
133
ret['location']['coroot']: Checkout root
134
ret['location']['branchroot']: Branch root
135
ret['related']['parentbranch']: Parent branch
136
ret['related']['publishbranch']: Publish to branch
137
ret['format']['control']: Control format
138
ret['format']['workingtree']: Working tree format
139
ret['format']['branch']: Branch format
140
ret['format']['repository']: Repository format
141
ret['locking']['workingtree']: Working tree lock status
142
ret['locking']['branch']: Branch lock status
143
ret['locking']['repository']: Repository lock status
144
ret['mrevbranch']['missing']: Missing revisions in branch
145
ret['mrevworking']['missing']: Missing revisions in working tree
146
ret['wtstats']['unchanged']: Unchanged files
147
ret['wtstats']['modified']: Modified files
148
ret['wtstats']['added']: Added files
149
ret['wtstats']['removed']: Removed files
150
ret['wtstats']['renamed']: Renamed files
151
ret['wtstats']['unknown']: Unknown files
152
ret['wtstats']['ignored']: Ingnored files
153
ret['wtstats']['subdirs']: Versioned subdirectories
154
ret['brstats']['revno']: Revisions in branch
155
ret['brstats']['commiters']: Number of commiters
156
ret['brstats']['age']: Age of branch in days
157
ret['brstats']['firstrev']: Time of first revision
158
ret['brstats']['lastrev']: Time of last revision
159
ret['repstats']['revisions']: Revisions in repository
160
ret['repstats']['size']: Size of repository in bytes
162
import bzrlib.bzrdir as bzrdir
167
a_bzrdir = bzrdir.BzrDir.open_containing(location)[0]
169
working = a_bzrdir.open_workingtree()
172
branch = working.branch
173
repository = branch.repository
174
control = working.bzrdir
176
ret['location'] = info_helper.get_location_info(repository, branch, working)
177
ret['related'] = info_helper.get_related_info(branch)
178
ret['format'] = info_helper.get_format_info(control, repository, branch, working)
179
ret['locking'] = info_helper.get_locking_info(repository, branch, working)
180
ret['mrevbranch'] = info_helper.get_missing_revisions_branch(branch)
181
ret['mrevworking'] = info_helper.get_missing_revisions_working(working)
182
ret['wtstats'] = info_helper.get_working_stats(working)
183
ret['brstats'] = info_helper.get_branch_stats(branch)
184
ret['repstats'] = info_helper.get_repository_stats(repository)
189
except (errors.NoWorkingTree, errors.NotLocalUrl):
193
branch = a_bzrdir.open_branch()
196
ret['location'] = info_helper.get_location_info(repository, branch)
197
ret['related'] = info_helper.get_related_info(branch)
198
ret['format'] = info_helper.get_format_info(control, repository, branch)
199
ret['locking'] = info_helper.get_locking_info(repository, branch)
200
ret['mrevbranch'] = info_helper.get_missing_revisions_branch(branch)
201
ret['brstats'] = info_helper.get_branch_stats(branch)
202
ret['repstats'] = info_helper.get_repository_stats(repository)
207
except errors.NotBranchError:
211
repository = a_bzrdir.open_repository()
212
repository.lock_read()
214
ret['location'] = info_helper.get_location_info(repository)
215
ret['format'] = info_helper.get_format_info(control, repository)
216
ret['locking'] = info_helper.get_locking_info(repository)
217
ret['repstats'] = info_helper.get_repository_stats(repository)
222
except errors.NoRepositoryPresent:
225
def log(location, timezone='original', verbose=False, show_ids=False,
226
forward=False, revision=None, log_format=None, message=None,
227
long=False, short=False, line=False):
228
""" Print log into a temporary file.
230
:param location: location of local/remote branch or file
232
:param timzone: requested timezone
234
:param verbose: verbose output
238
:param forward: if True, start from the earliest entry
240
:param revision: revision range as a list ([from, to])
242
:param log_format: line, short, long
244
:param message: show revisions whose message matches this regexp
246
:param long: long log format
248
:param short: short log format
250
:param line: line log format
252
:return: full path to the temporary file containing the log (the frontend has to remove it!)
254
from tempfile import mkstemp
256
from bzrlib import bzrdir
257
from bzrlib.builtins import get_log_format
258
from bzrlib.log import log_formatter, show_log
259
from bzrlib.revisionspec import RevisionSpec_int
261
assert message is None or isinstance(message, basestring), \
262
"invalid message argument %r" % message
263
direction = (forward and 'forward') or 'reverse'
268
# find the file id to log:
269
dir, fp = bzrdir.BzrDir.open_containing(location)
270
b = dir.open_branch()
274
inv = dir.open_workingtree().inventory
275
except (errors.NotBranchError, errors.NotLocalUrl):
276
# either no tree, or is remote.
277
inv = b.basis_tree().inventory
278
file_id = inv.path2id(fp)
280
if revision is not None:
281
if len(revision) >= 1:
282
revision[0] = RevisionSpec_int(revision[0])
283
if len(revision) == 2:
284
revision[1] = RevisionSpec_int(revision[1])
289
elif len(revision) == 1:
290
rev1 = rev2 = revision[0].in_history(b).revno
291
elif len(revision) == 2:
292
if revision[0].spec is None:
293
# missing begin-range means first revision
296
rev1 = revision[0].in_history(b).revno
298
if revision[1].spec is None:
299
# missing end-range means last known revision
302
rev2 = revision[1].in_history(b).revno
304
raise RevisionValueError
306
# By this point, the revision numbers are converted to the +ve
307
# form if they were supplied in the -ve form, so we can do
308
# this comparison in relative safety
310
(rev2, rev1) = (rev1, rev2)
312
if (log_format == None):
313
default = b.get_config().log_format()
314
log_format = get_log_format(long=long, short=short, line=line,
317
tmpfile = mkstemp(prefix='olive_')
318
tmpfp = open(tmpfile[1], 'w')
320
lf = log_formatter(log_format,
323
show_timezone=timezone)
337
def nick(branch, nickname=None):
338
""" Get or set nickname.
340
:param branch: path to the branch
342
:param nickname: if specified, the nickname will be set
347
branch = Branch.open_containing(branch)[0]
348
except errors.NotBranchError:
351
if nickname is not None:
352
branch.nick = nickname
357
""" Get current revision number for specified branch
359
:param branch: path to the branch
361
:return: revision number
364
revno = Branch.open_containing(branch)[0].revno()
365
except errors.NotBranchError:
371
""" Get version information from bzr
373
:return: bzrlib version
375
return bzrlib.__version__
377
def whoami(branch=None, email=False):
378
""" Get user's data (name and email address)
380
:param branch: if specified, the user's data will be looked up in the branch's config
382
:param email: if True, only the email address will be returned
384
:return: user info (only email address if email is True)
386
from bzrlib.workingtree import WorkingTree
388
if branch is not None:
390
b = WorkingTree.open_containing(u'.')[0].branch
391
config = bzrlib.config.BranchConfig(b)
392
except NotBranchError:
393
config = bzrlib.config.GlobalConfig()
395
config = bzrlib.config.GlobalConfig()
398
return config.user_email()
400
return config.username()