/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
3250.4.1 by Martin Albisetti
Added integration guide for developers
1
=======================
2
Integrating with Bazaar
3
=======================
4
5
This page should hopefully become a quick guide to integrating other (Python-based) software with Bazaar.
6
7
Manipulating the Working Tree
8
=============================
9
Most objects in Bazaar are in files, named after the class they contain. To manipulate the Working Tree we need a valid WorkingTree object, which is loaded from the workingtree.py file, eg::
10
11
  #!python
12
  from bzrlib import workingtree
13
  wt = workingtree.WorkingTree.open('/home/jebw/bzrtest')
14
15
16
This gives us a WorkingTree object, which has various methods spread over itself, and its parent classes MutableTree and Tree - its worth having a look through these three files (workingtree.py, mutabletree.py and tree.py) to see which methods are available.
17
18
Checking Status
19
===============
20
To check status (equivalent of bzr status) we need to create a Delta object showing changes::
21
22
  #!python
23
  from bzrlib import delta
24
  changes = wt.changes_from(wt.basis_tree())
25
26
27
This gives us Delta object with different lists of files for each type of change, eg changes.added is a list of added files, changes.removed is list of removed files, changes.modified is a list of modified files. The contents of the lists aren't just filenames, but included other information as well. To grab just the filename we want the first value, eg::
28
29
  #!python
30
  print("list of newly added files")
31
  for filename in changes.added:
32
    print("%s has been added" % filename[0])
33
34
35
The exception to this is changes.renamed, where the list returned for each renamed files contains both the old and new names -- one or both may interest you, depending on what you're doing.  
36
37
For example::
38
39
  #!python
40
  print("list of renamed files")
41
  for filename in changes.renamed:
42
    print("%s has been renamed to %s" % (filename[0], filename[1]))
43
44
45
Adding Files
46
============
47
48
If you want to add files the same way `bzr add` does, you can use MutableTree.smart_add.  By default, this is recursive. Paths can either be absolute or relative to the workingtree::
49
50
  #!python
51
  wt.smart_add(['dir1/filea.txt', 'fileb.txt', '/home/jebw/bzrtesttree/filec.txt'])
52
53
54
For more precise control over which files to add, use MutableTree.add::
55
56
  #!python
57
  wt.add(['dir1/filea.txt', 'fileb.txt', '/home/jebw/bzrtesttree/filec.txt'])
58
59
60
Removing Files
61
==============
62
63
You can remove multiple files at once.  The file paths need to be relative to the workingtree::
64
65
  #!python
66
  wt.remove(['filea.txt', 'fileb.txt', 'dir1'])
67
68
69
By default, the files are not deleted, just removed from the inventory.  To delete them from the filesystem as well::
70
71
  #!python
72
  wt.remove(['filea.txt', 'fileb.txt', 'dir1'], keep_files=False)
73
74
75
Renaming a File
76
===============
77
78
You can rename one file to a different name using WorkingTree.rename_one.  You just provide the old and new names, eg::
79
80
  #!python
81
  wt.rename_one('oldfile.txt','newfile.txt')
82
83
84
Moving Files
85
============
86
87
You can move multiple files from one directory into another using WorkingTree.move::
88
89
  #!python
90
  wt.move(['olddir/file.txt'], 'newdir')
91
92
93
More complicated renames/moves can be done with transform.TreeTransform, which is outside the scope of this document.
94
95
96
Committing Changes
97
==================
98
99
To commit _all_ the changes to our working tree we can just call the WorkingTree's commit method, giving it a commit message, eg::
100
101
  #!python
102
  wt.commit('this is my commit message')
103
104
105
To commit only certain files, we need to provide a list of filenames which we want committing, eg::
106
107
  #!python
108
  wt.commit(message='this is my commit message', specific_files=['fileA.txt', 'dir2/fileB.txt', 'fileD.txt'])
109
110
111
Generating a Log for a File
112
===========================
113
114
Generating a log is, in itself, simple.  Grab a branch (see below) and pass it to show_log together with a log formatter, eg::
115
116
  #!python
117
  from bzrlib import log
118
  from bzrlib import branch
119
  
120
  b = branch.Branch.open('/path/to/bazaar/branch')
121
  lf = log.LongLogFormatter(to_file=sys.stdout)
122
  log.show_log(b, lf)
123
124
125
Three log formatters are included with bzrlib: LongLogFormatter, ShortLogFormatter and LineLogFormatter.  These provide long, short and single-line log output formats. It's also possible to write your own in very little code.
126
127
Annotating a File
128
=================
129
130
To annotate a file, we want to walk every line of a file, retrieving the revision which last modified/created that line and then retrieving the information for that revision.
131
132
First we get an annotation iterator for the file we are interested in::
133
134
  #!python
135
  tree, relpath = workingtree.WorkingTree.open_containing('/path/to/file.txt')
136
  fileid = tree.path2id(relpath)
137
  annotation = list(tree.annotate_iter(fileid))
138
139
140
To avoid repeatedly retrieving the same revisions we grab all revisions associated with the file at once and build up a map of id to revision information. We also build an map of revision numbers, again indexed by the revision id::
141
142
  #!python
143
  revision_ids = set(revision_id for revision_id, text in annotation)
144
  revisions = tree.branch.repository.get_revisions(revision_ids)
145
  revision_map = dict(izip(revision_ids, revisions))
146
  revno_map = tree.branch.get_revision_id_to_revno_map()
147
148
149
Finally, we use our annotation iterator to walk the lines of the file, displaying the information from our revision maps as we go::
150
151
  #!python
152
  for revision_id, text in annotation :
153
      rev = revision_map[revision_id]
154
      revno = revno_map[revision_id]
155
      revno_string = '.'.join(str(i) for i in revno)
156
      print "%s, %s: %s" % (revno_string, rev.committer, text)
157
158
159
Working with branches
160
=====================
161
162
To work with a branch you need a branch object, created from your branch::
163
164
  #!python
165
  from bzrlib import branch
166
  
167
  b = branch.Branch.open('/home/jebw/bzrtest')
168
169
170
Branching from an existing branch
171
=================================
172
173
To branch you create a branch object representing the branch you are branching from, and supply a path/url to the new branch location. The following code clones the bzr.dev branch (the latest copy of the Bazaar source code) - be warned it has to download 60meg so takes a while to run with no feedback::
174
175
  #!python
176
  from bzrlib import branch
177
  
178
  b = branch.Branch.open('http://bazaar-vcs.org/bzr/bzr.dev')
179
  nb = b.bzrdir.sprout('/tmp/newBzrBranch').open_branch()
180
181
182
This provides no feedback, since Bazaar automatically uses the 'silent' UI. 
183
184
185
Pushing and pulling branches
186
============================
187
188
To push a branch you need to open the source and destination branches, then just call push with the other branch as a parameter::
189
190
  #!python
191
  from bzrlib import branch
192
  
193
  b1 = branch.Branch.open('file:///home/user/mybranch')
194
  b2 = branch.Branch.open('http://bazaar-vcs.org/bzr/bzr.dev')
195
  b1.push(b2)
196
197
198
Pulling is much the same::
199
200
  #!python
201
  b1.pull(b2)
202
203
204
If you have a working tree, as well as a branch, you should use WorkingTree.pull, not Branch.pull.
205
206
This won't handle conflicts automatically though, so any conflicts will be left in the working tree for the user to resolve.
207
208
209
Checkout from an existing branch
210
================================
211
212
This performs a Lightweight checkout from an existing Branch::
213
214
  #!python
215
  from bzrlib import bzrdir
216
  
217
  accelerator_tree, source = bzrdir.BzrDir.open_tree_or_branch('http://bazaar-vcs.org/bzr/bzr.dev')
218
  source.create_checkout('/tmp/newBzrCheckout', None, True, accelerator_tree)
219
220
221
To make a heavyweight checkout, change the last line to::
222
223
  source.create_checkout('/tmp/newBzrCheckout', None, False, accelerator_tree
224
225
==================
226
History Operations
227
==================
228
229
Finding the last revision number or id
230
======================================
231
232
To get the last revision number and id of a branch use::
233
234
  #!python
235
  revision_number, revision_id = branch.last_revision_info()
236
237
238
If all you care about is the revision_id there is also the
239
method::
240
241
  #!python
242
  revision_id = branch.last_revision()
243
244
245
Getting the list of revision ids that make up a branch
246
======================================================
247
248
IMPORTANT: This should be avoided wherever possible, as it scales with the length of history::
249
250
  #!python
251
  revisions = branch.revision_history()
252
253
now revisions[0] is the revision id of the first commit, and revs[-1] is the revision
254
id of the most recent. Note that if all you want is the last revision then
255
you should use branch.last_revision() as described above, as it is
256
vastly more efficient.
257
258
259
Getting a Revision object from a revision id
260
============================================
261
262
The Revision object has attributes like "message" to get the information
263
about the revision::
264
265
  #!python
266
  repo = branch.repository
267
  revision = repo.get_revision(rev_id)
268
269
270
Accessing the files from a revision
271
===================================
272
273
To get the file contents and tree shape for a specific revision you need
274
a RevisionTree. These are supplied by the repository for a specific
275
revision id::
276
277
  #!python
278
  revtree = repo.revision_tree(rev_id)
279
280
There's a lot going on in a RevisionTree, but there are a couple of things
281
that may be interesting::
282
283
  #!python
284
  revtree.changes_from(other_revtree)
285
286
gives you a TreeDelta which you is a form of diff.  
287
288
A more regular and precise comparison can be derived from ``Tree.iter_changes``::
289
290
  #!python
291
  revtree.iter_changes(other_revtree)
292
293
See the API documentation for more details.
294
295
296
The most common way to list files in a tree is `Tree.iter_entries()`.  The simplest way to get file content is `Tree.get_file()`.  The best way to retrieve file content for large numbers of files `Tree.iter_files_bytes()`.
297
298
299
Manipulating the Repository Directly
300
====================================
301
302
TBD (by someone else who knows what they're doing)
303
(If someone will describe the operations they're interested in, I can take a stab at it -- AaronBentley)