~bzr-pqm/bzr/bzr.dev

3250.4.1 by Martin Albisetti
Added integration guide for developers
1
=======================
2
Integrating with Bazaar
3
=======================
4
5225.2.13 by Martin Pool
More reorganization of the developer documentation
5
This document provides some general observations on integrating with
6
Bazaar and some recipes for typical tasks.  It is intended to be useful to
7
someone developing either a plugin or some other piece of software that
8
integrates with bzr.  If you want to know about a topic that's not covered
9
here, just ask us.
10
11
5225.2.4 by Martin Pool
ReST format fixes
12
13
5225.2.6 by Martin Pool
mention bzrlib.initialize and get_command
14
Starting with bzrlib
15
====================
16
5641.2.1 by Andrew Bennetts
Fix some formatting nits in doc/developers/overview.txt, and expand the content a little.
17
Within bzr
18
----------
19
20
When using bzrlib within the ``bzr`` program (for instance as a bzr
21
plugin), bzrlib's global state is already available for use.
22
23
From outside bzr
24
----------------
25
26
To use bzrlib outside of ``bzr`` some global state needs to be setup.
27
bzrlib needs ways to handle user input, passwords, a place to emit
28
progress bars, logging setup appropriately for your program. The easiest
29
way to set all this up in the same fashion ``bzr`` does is to call
5728.4.1 by Martin Pool
bzrlib.initialize now does what you'd expect
30
``bzrlib.initialize``. 
31
32
This returns a context manager within which bzrlib functions will work
33
correctly. See the pydoc for ``bzrlib.initialize`` for more information. 
34
(You can get away without entering the context manager, because the setup
35
work happens directly from ``initialize``.)
36
37
In Python 2.4 the ``with`` keyword is not supported and
5641.2.1 by Andrew Bennetts
Fix some formatting nits in doc/developers/overview.txt, and expand the content a little.
38
so you need to use the context manager manually::
39
40
  # This sets up your ~/.bzr.log, ui factory and so on and so forth. It is
41
  # not safe to use as a doctest.
42
  library_state = bzrlib.initialize()
43
  library_state.__enter__()
44
  try:
45
      pass
46
      # do stuff here
47
  finally:
48
      library_state.__exit__(None, None, None)
5225.2.6 by Martin Pool
mention bzrlib.initialize and get_command
49
50
51
Running bzr commands
52
====================
53
54
To run command-line commands in-process::
55
56
  from bzrlib.commands import get_command
57
  
58
  cmd = get_command('version')
59
  cmd.run([])
60
  
61
This will send output through the current UIFactory; you can redirect this
62
elsewhere through the parameters to `bzrlib.initialize`.
63
5225.2.4 by Martin Pool
ReST format fixes
64
3250.4.1 by Martin Albisetti
Added integration guide for developers
65
Manipulating the Working Tree
66
=============================
3250.4.5 by Martin Albisetti
Removed trailing whitespaces
67
Most objects in Bazaar are in files, named after the class they contain.
68
To manipulate the Working Tree we need a valid WorkingTree object, which
3250.4.4 by Martin Albisetti
Shortened to under 80 characters per line, and removed all wiki-specific information
69
is loaded from the workingtree.py file, eg::
3250.4.1 by Martin Albisetti
Added integration guide for developers
70
71
  from bzrlib import workingtree
72
  wt = workingtree.WorkingTree.open('/home/jebw/bzrtest')
73
74
3250.4.5 by Martin Albisetti
Removed trailing whitespaces
75
This gives us a WorkingTree object, which has various methods spread over
5538.1.1 by Zearin
Fixed “its” vs “it's”.
76
itself, and its parent classes MutableTree and Tree - it's worth having a
3250.4.5 by Martin Albisetti
Removed trailing whitespaces
77
look through these three files (workingtree.py, mutabletree.py and tree.py)
3250.4.4 by Martin Albisetti
Shortened to under 80 characters per line, and removed all wiki-specific information
78
to see which methods are available.
3250.4.1 by Martin Albisetti
Added integration guide for developers
79
3250.4.6 by Martin Albisetti
Added changes sent by Aaron Bently
80
Compare trees
5225.2.4 by Martin Pool
ReST format fixes
81
-------------
82
3250.4.6 by Martin Albisetti
Added changes sent by Aaron Bently
83
There are two methods for comparing trees: ``changes_from`` and
84
``iter_changes``.  ``iter_changes`` is more regular and precise, but it is
85
somewhat harder to work with.  See the API documentation for more details.
86
87
``changes_from`` creates a Delta object showing changes::
3250.4.1 by Martin Albisetti
Added integration guide for developers
88
89
  from bzrlib import delta
90
  changes = wt.changes_from(wt.basis_tree())
91
3250.4.6 by Martin Albisetti
Added changes sent by Aaron Bently
92
This gives us a Delta object, which has several lists of files for each type of
3250.4.5 by Martin Albisetti
Removed trailing whitespaces
93
change, eg changes.added is a list of added files, changes.removed is list
94
of removed files, changes.modified is a list of modified files. The contents
3250.4.6 by Martin Albisetti
Added changes sent by Aaron Bently
95
of the lists aren't just filenames, but include other information as well.
3344.1.2 by Martin Pool
Fix ReST syntax in integration guide
96
To grab just the filename we want the first value, eg::
3250.4.1 by Martin Albisetti
Added integration guide for developers
97
98
  print("list of newly added files")
99
  for filename in changes.added:
100
    print("%s has been added" % filename[0])
101
102
3250.4.5 by Martin Albisetti
Removed trailing whitespaces
103
The exception to this is changes.renamed, where the list returned for each
104
renamed files contains both the old and new names -- one or both may interest
105
you, depending on what you're doing.
3250.4.1 by Martin Albisetti
Added integration guide for developers
106
107
For example::
108
109
  print("list of renamed files")
110
  for filename in changes.renamed:
111
    print("%s has been renamed to %s" % (filename[0], filename[1]))
112
113
114
Adding Files
5225.2.4 by Martin Pool
ReST format fixes
115
------------
3250.4.1 by Martin Albisetti
Added integration guide for developers
116
3250.4.5 by Martin Albisetti
Removed trailing whitespaces
117
If you want to add files the same way ``bzr add`` does, you can use
118
MutableTree.smart_add.  By default, this is recursive. Paths can either be
3250.4.4 by Martin Albisetti
Shortened to under 80 characters per line, and removed all wiki-specific information
119
absolute or relative to the workingtree::
3250.4.1 by Martin Albisetti
Added integration guide for developers
120
3250.4.5 by Martin Albisetti
Removed trailing whitespaces
121
  wt.smart_add(['dir1/filea.txt', 'fileb.txt',
3250.4.4 by Martin Albisetti
Shortened to under 80 characters per line, and removed all wiki-specific information
122
                '/home/jebw/bzrtesttree/filec.txt'])
3250.4.1 by Martin Albisetti
Added integration guide for developers
123
124
125
For more precise control over which files to add, use MutableTree.add::
126
127
  wt.add(['dir1/filea.txt', 'fileb.txt', '/home/jebw/bzrtesttree/filec.txt'])
128
129
130
Removing Files
5225.2.4 by Martin Pool
ReST format fixes
131
--------------
3250.4.1 by Martin Albisetti
Added integration guide for developers
132
3250.4.5 by Martin Albisetti
Removed trailing whitespaces
133
You can remove multiple files at once.  The file paths need to be relative
3250.4.4 by Martin Albisetti
Shortened to under 80 characters per line, and removed all wiki-specific information
134
to the workingtree::
3250.4.1 by Martin Albisetti
Added integration guide for developers
135
136
  wt.remove(['filea.txt', 'fileb.txt', 'dir1'])
137
138
3250.4.5 by Martin Albisetti
Removed trailing whitespaces
139
By default, the files are not deleted, just removed from the inventory.
3250.4.4 by Martin Albisetti
Shortened to under 80 characters per line, and removed all wiki-specific information
140
To delete them from the filesystem as well::
3250.4.1 by Martin Albisetti
Added integration guide for developers
141
142
  wt.remove(['filea.txt', 'fileb.txt', 'dir1'], keep_files=False)
143
144
145
Renaming a File
5225.2.4 by Martin Pool
ReST format fixes
146
---------------
3250.4.1 by Martin Albisetti
Added integration guide for developers
147
3250.4.5 by Martin Albisetti
Removed trailing whitespaces
148
You can rename one file to a different name using WorkingTree.rename_one.
3250.4.4 by Martin Albisetti
Shortened to under 80 characters per line, and removed all wiki-specific information
149
You just provide the old and new names, eg::
3250.4.1 by Martin Albisetti
Added integration guide for developers
150
151
  wt.rename_one('oldfile.txt','newfile.txt')
152
153
154
Moving Files
5225.2.4 by Martin Pool
ReST format fixes
155
------------
3250.4.1 by Martin Albisetti
Added integration guide for developers
156
3250.4.5 by Martin Albisetti
Removed trailing whitespaces
157
You can move multiple files from one directory into another using
3250.4.4 by Martin Albisetti
Shortened to under 80 characters per line, and removed all wiki-specific information
158
WorkingTree.move::
3250.4.1 by Martin Albisetti
Added integration guide for developers
159
160
  wt.move(['olddir/file.txt'], 'newdir')
161
162
3250.4.5 by Martin Albisetti
Removed trailing whitespaces
163
More complicated renames/moves can be done with transform.TreeTransform,
3250.4.4 by Martin Albisetti
Shortened to under 80 characters per line, and removed all wiki-specific information
164
which is outside the scope of this document.
3250.4.1 by Martin Albisetti
Added integration guide for developers
165
166
167
Committing Changes
5225.2.4 by Martin Pool
ReST format fixes
168
------------------
3250.4.1 by Martin Albisetti
Added integration guide for developers
169
3250.4.5 by Martin Albisetti
Removed trailing whitespaces
170
To commit _all_ the changes to our working tree we can just call the
3250.4.4 by Martin Albisetti
Shortened to under 80 characters per line, and removed all wiki-specific information
171
WorkingTree's commit method, giving it a commit message, eg::
3250.4.1 by Martin Albisetti
Added integration guide for developers
172
173
  wt.commit('this is my commit message')
174
175
3250.4.5 by Martin Albisetti
Removed trailing whitespaces
176
To commit only certain files, we need to provide a list of filenames which we
3250.4.4 by Martin Albisetti
Shortened to under 80 characters per line, and removed all wiki-specific information
177
want committing, eg::
3250.4.1 by Martin Albisetti
Added integration guide for developers
178
3250.4.4 by Martin Albisetti
Shortened to under 80 characters per line, and removed all wiki-specific information
179
  wt.commit(message='this is my commit message', specific_files=['fileA.txt',
180
            'dir2/fileB.txt', 'fileD.txt'])
3250.4.1 by Martin Albisetti
Added integration guide for developers
181
182
183
Generating a Log for a File
184
===========================
185
3250.4.5 by Martin Albisetti
Removed trailing whitespaces
186
Generating a log is, in itself, simple.  Grab a branch (see below) and pass
3250.4.4 by Martin Albisetti
Shortened to under 80 characters per line, and removed all wiki-specific information
187
it to show_log together with a log formatter, eg::
3250.4.1 by Martin Albisetti
Added integration guide for developers
188
189
  from bzrlib import log
190
  from bzrlib import branch
3250.4.5 by Martin Albisetti
Removed trailing whitespaces
191
3250.4.1 by Martin Albisetti
Added integration guide for developers
192
  b = branch.Branch.open('/path/to/bazaar/branch')
193
  lf = log.LongLogFormatter(to_file=sys.stdout)
194
  log.show_log(b, lf)
195
196
3250.4.5 by Martin Albisetti
Removed trailing whitespaces
197
Three log formatters are included with bzrlib: LongLogFormatter,
198
ShortLogFormatter and LineLogFormatter.  These provide long, short and
199
single-line log output formats. It's also possible to write your own in
3250.4.4 by Martin Albisetti
Shortened to under 80 characters per line, and removed all wiki-specific information
200
very little code.
3250.4.1 by Martin Albisetti
Added integration guide for developers
201
202
Annotating a File
203
=================
204
3250.4.5 by Martin Albisetti
Removed trailing whitespaces
205
To annotate a file, we want to walk every line of a file, retrieving the
206
revision which last modified/created that line and then retrieving the
3250.4.4 by Martin Albisetti
Shortened to under 80 characters per line, and removed all wiki-specific information
207
information for that revision.
3250.4.1 by Martin Albisetti
Added integration guide for developers
208
209
First we get an annotation iterator for the file we are interested in::
210
211
  tree, relpath = workingtree.WorkingTree.open_containing('/path/to/file.txt')
212
  fileid = tree.path2id(relpath)
213
  annotation = list(tree.annotate_iter(fileid))
214
215
3250.4.5 by Martin Albisetti
Removed trailing whitespaces
216
To avoid repeatedly retrieving the same revisions we grab all revisions
217
associated with the file at once and build up a map of id to revision
218
information. We also build an map of revision numbers, again indexed
3250.4.4 by Martin Albisetti
Shortened to under 80 characters per line, and removed all wiki-specific information
219
by the revision id::
3250.4.1 by Martin Albisetti
Added integration guide for developers
220
221
  revision_ids = set(revision_id for revision_id, text in annotation)
222
  revisions = tree.branch.repository.get_revisions(revision_ids)
223
  revision_map = dict(izip(revision_ids, revisions))
224
  revno_map = tree.branch.get_revision_id_to_revno_map()
225
226
3250.4.5 by Martin Albisetti
Removed trailing whitespaces
227
Finally, we use our annotation iterator to walk the lines of the file,
3250.4.4 by Martin Albisetti
Shortened to under 80 characters per line, and removed all wiki-specific information
228
displaying the information from our revision maps as we go::
3250.4.1 by Martin Albisetti
Added integration guide for developers
229
230
  for revision_id, text in annotation :
231
      rev = revision_map[revision_id]
232
      revno = revno_map[revision_id]
233
      revno_string = '.'.join(str(i) for i in revno)
234
      print "%s, %s: %s" % (revno_string, rev.committer, text)
235
236
237
Working with branches
238
=====================
239
240
To work with a branch you need a branch object, created from your branch::
241
242
  from bzrlib import branch
3250.4.5 by Martin Albisetti
Removed trailing whitespaces
243
3250.4.1 by Martin Albisetti
Added integration guide for developers
244
  b = branch.Branch.open('/home/jebw/bzrtest')
245
246
247
Branching from an existing branch
5225.2.4 by Martin Pool
ReST format fixes
248
---------------------------------
3250.4.1 by Martin Albisetti
Added integration guide for developers
249
3250.4.5 by Martin Albisetti
Removed trailing whitespaces
250
To branch you create a branch object representing the branch you are
251
branching from, and supply a path/url to the new branch location.
252
The following code clones the bzr.dev branch (the latest copy of the Bazaar
253
source code) - be warned it has to download 60meg so takes a while to run
3250.4.4 by Martin Albisetti
Shortened to under 80 characters per line, and removed all wiki-specific information
254
with no feedback::
3250.4.1 by Martin Albisetti
Added integration guide for developers
255
256
  from bzrlib import branch
3250.4.5 by Martin Albisetti
Removed trailing whitespaces
257
4675.2.2 by Robert Collins
Replace bazaar-vcs.org/bzr/ references with launchpad hosting urls in developer docs.
258
  b = branch.Branch.open('http://bazaar.launchpad.net/~bzr-pqm/bzr/bzr.dev')
3250.4.1 by Martin Albisetti
Added integration guide for developers
259
  nb = b.bzrdir.sprout('/tmp/newBzrBranch').open_branch()
260
261
3250.4.5 by Martin Albisetti
Removed trailing whitespaces
262
This provides no feedback, since Bazaar automatically uses the 'silent' UI.
3250.4.1 by Martin Albisetti
Added integration guide for developers
263
264
265
Pushing and pulling branches
5225.2.4 by Martin Pool
ReST format fixes
266
----------------------------
3250.4.1 by Martin Albisetti
Added integration guide for developers
267
3250.4.5 by Martin Albisetti
Removed trailing whitespaces
268
To push a branch you need to open the source and destination branches, then
3250.4.4 by Martin Albisetti
Shortened to under 80 characters per line, and removed all wiki-specific information
269
just call push with the other branch as a parameter::
3250.4.1 by Martin Albisetti
Added integration guide for developers
270
271
  from bzrlib import branch
3250.4.5 by Martin Albisetti
Removed trailing whitespaces
272
3250.4.1 by Martin Albisetti
Added integration guide for developers
273
  b1 = branch.Branch.open('file:///home/user/mybranch')
4675.2.2 by Robert Collins
Replace bazaar-vcs.org/bzr/ references with launchpad hosting urls in developer docs.
274
  b2 = branch.Branch.open('http://bazaar.launchpad.net/~bzr-pqm/bzr/bzr.dev')
3250.4.1 by Martin Albisetti
Added integration guide for developers
275
  b1.push(b2)
276
277
278
Pulling is much the same::
279
280
  b1.pull(b2)
281
282
3250.4.5 by Martin Albisetti
Removed trailing whitespaces
283
If you have a working tree, as well as a branch, you should use
3250.4.4 by Martin Albisetti
Shortened to under 80 characters per line, and removed all wiki-specific information
284
WorkingTree.pull, not Branch.pull.
3250.4.1 by Martin Albisetti
Added integration guide for developers
285
3250.4.5 by Martin Albisetti
Removed trailing whitespaces
286
This won't handle conflicts automatically though, so any conflicts will be
3250.4.4 by Martin Albisetti
Shortened to under 80 characters per line, and removed all wiki-specific information
287
left in the working tree for the user to resolve.
3250.4.1 by Martin Albisetti
Added integration guide for developers
288
289
290
Checkout from an existing branch
291
================================
292
293
This performs a Lightweight checkout from an existing Branch::
294
295
  from bzrlib import bzrdir
3250.4.5 by Martin Albisetti
Removed trailing whitespaces
296
3250.4.4 by Martin Albisetti
Shortened to under 80 characters per line, and removed all wiki-specific information
297
  accelerator_tree, source = bzrdir.BzrDir.open_tree_or_branch('http:URL')
3250.4.1 by Martin Albisetti
Added integration guide for developers
298
  source.create_checkout('/tmp/newBzrCheckout', None, True, accelerator_tree)
299
300
301
To make a heavyweight checkout, change the last line to::
302
303
  source.create_checkout('/tmp/newBzrCheckout', None, False, accelerator_tree
304
4634.39.32 by Ian Clatworthy
proper Contents panel in bzr-developers.chm
305
3250.4.1 by Martin Albisetti
Added integration guide for developers
306
History Operations
307
==================
308
309
Finding the last revision number or id
4634.39.32 by Ian Clatworthy
proper Contents panel in bzr-developers.chm
310
--------------------------------------
3250.4.1 by Martin Albisetti
Added integration guide for developers
311
312
To get the last revision number and id of a branch use::
313
314
  revision_number, revision_id = branch.last_revision_info()
315
316
317
If all you care about is the revision_id there is also the
318
method::
319
320
  revision_id = branch.last_revision()
321
322
323
Getting the list of revision ids that make up a branch
4634.39.32 by Ian Clatworthy
proper Contents panel in bzr-developers.chm
324
------------------------------------------------------
3250.4.1 by Martin Albisetti
Added integration guide for developers
325
3250.4.5 by Martin Albisetti
Removed trailing whitespaces
326
IMPORTANT: This should be avoided wherever possible, as it scales with the
3250.4.4 by Martin Albisetti
Shortened to under 80 characters per line, and removed all wiki-specific information
327
length of history::
3250.4.1 by Martin Albisetti
Added integration guide for developers
328
329
  revisions = branch.revision_history()
330
3250.4.5 by Martin Albisetti
Removed trailing whitespaces
331
now revisions[0] is the revision id of the first commit, and revs[-1] is the
332
revision id of the most recent. Note that if all you want is the last
333
revision then you should use branch.last_revision() as described above, as
3250.4.4 by Martin Albisetti
Shortened to under 80 characters per line, and removed all wiki-specific information
334
it is vastly more efficient.
3250.4.1 by Martin Albisetti
Added integration guide for developers
335
336
337
Getting a Revision object from a revision id
4634.39.32 by Ian Clatworthy
proper Contents panel in bzr-developers.chm
338
--------------------------------------------
3250.4.1 by Martin Albisetti
Added integration guide for developers
339
340
The Revision object has attributes like "message" to get the information
341
about the revision::
342
343
  repo = branch.repository
344
  revision = repo.get_revision(rev_id)
345
346
347
Accessing the files from a revision
4634.39.32 by Ian Clatworthy
proper Contents panel in bzr-developers.chm
348
-----------------------------------
3250.4.1 by Martin Albisetti
Added integration guide for developers
349
350
To get the file contents and tree shape for a specific revision you need
351
a RevisionTree. These are supplied by the repository for a specific
352
revision id::
353
354
  revtree = repo.revision_tree(rev_id)
355
3250.4.6 by Martin Albisetti
Added changes sent by Aaron Bently
356
RevisionTrees, like all trees, can be compared as described in "Comparing
357
Trees" above.
3250.4.1 by Martin Albisetti
Added integration guide for developers
358
3250.4.5 by Martin Albisetti
Removed trailing whitespaces
359
The most common way to list files in a tree is ``Tree.iter_entries()``.
360
The simplest way to get file content is ``Tree.get_file()``.  The best way
361
to retrieve file content for large numbers of files `Tree.iter_files_bytes()``
3250.4.4 by Martin Albisetti
Shortened to under 80 characters per line, and removed all wiki-specific information
362