##// END OF EJS Templates
bundlerepo: backout dbf292f65b09...
Matt Mackall -
r21694:c08a22bf default
parent child Browse files
Show More
@@ -1,400 +1,400 b''
1 # bundlerepo.py - repository class for viewing uncompressed bundles
1 # bundlerepo.py - repository class for viewing uncompressed bundles
2 #
2 #
3 # Copyright 2006, 2007 Benoit Boissinot <bboissin@gmail.com>
3 # Copyright 2006, 2007 Benoit Boissinot <bboissin@gmail.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 """Repository class for viewing uncompressed bundles.
8 """Repository class for viewing uncompressed bundles.
9
9
10 This provides a read-only repository interface to bundles as if they
10 This provides a read-only repository interface to bundles as if they
11 were part of the actual repository.
11 were part of the actual repository.
12 """
12 """
13
13
14 from node import nullid
14 from node import nullid
15 from i18n import _
15 from i18n import _
16 import os, tempfile, shutil
16 import os, tempfile, shutil
17 import changegroup, util, mdiff, discovery, cmdutil, scmutil, exchange
17 import changegroup, util, mdiff, discovery, cmdutil, scmutil, exchange
18 import localrepo, changelog, manifest, filelog, revlog, error
18 import localrepo, changelog, manifest, filelog, revlog, error
19
19
20 class bundlerevlog(revlog.revlog):
20 class bundlerevlog(revlog.revlog):
21 def __init__(self, opener, indexfile, bundle, linkmapper):
21 def __init__(self, opener, indexfile, bundle, linkmapper):
22 # How it works:
22 # How it works:
23 # To retrieve a revision, we need to know the offset of the revision in
23 # To retrieve a revision, we need to know the offset of the revision in
24 # the bundle (an unbundle object). We store this offset in the index
24 # the bundle (an unbundle object). We store this offset in the index
25 # (start). The base of the delta is stored in the base field.
25 # (start). The base of the delta is stored in the base field.
26 #
26 #
27 # To differentiate a rev in the bundle from a rev in the revlog, we
27 # To differentiate a rev in the bundle from a rev in the revlog, we
28 # check revision against repotiprev.
28 # check revision against repotiprev.
29 opener = scmutil.readonlyvfs(opener)
29 opener = scmutil.readonlyvfs(opener)
30 revlog.revlog.__init__(self, opener, indexfile)
30 revlog.revlog.__init__(self, opener, indexfile)
31 self.bundle = bundle
31 self.bundle = bundle
32 n = len(self)
32 n = len(self)
33 self.repotiprev = n - 1
33 self.repotiprev = n - 1
34 chain = None
34 chain = None
35 self.bundlerevs = set() # used by 'bundle()' revset expression
35 self.bundlerevs = set() # used by 'bundle()' revset expression
36 while True:
36 while True:
37 chunkdata = bundle.deltachunk(chain)
37 chunkdata = bundle.deltachunk(chain)
38 if not chunkdata:
38 if not chunkdata:
39 break
39 break
40 node = chunkdata['node']
40 node = chunkdata['node']
41 p1 = chunkdata['p1']
41 p1 = chunkdata['p1']
42 p2 = chunkdata['p2']
42 p2 = chunkdata['p2']
43 cs = chunkdata['cs']
43 cs = chunkdata['cs']
44 deltabase = chunkdata['deltabase']
44 deltabase = chunkdata['deltabase']
45 delta = chunkdata['delta']
45 delta = chunkdata['delta']
46
46
47 size = len(delta)
47 size = len(delta)
48 start = bundle.tell() - size
48 start = bundle.tell() - size
49
49
50 link = linkmapper(cs)
50 link = linkmapper(cs)
51 if node in self.nodemap:
51 if node in self.nodemap:
52 # this can happen if two branches make the same change
52 # this can happen if two branches make the same change
53 chain = node
53 chain = node
54 self.bundlerevs.add(self.nodemap[node])
54 self.bundlerevs.add(self.nodemap[node])
55 continue
55 continue
56
56
57 for p in (p1, p2):
57 for p in (p1, p2):
58 if p not in self.nodemap:
58 if p not in self.nodemap:
59 raise error.LookupError(p, self.indexfile,
59 raise error.LookupError(p, self.indexfile,
60 _("unknown parent"))
60 _("unknown parent"))
61
61
62 if deltabase not in self.nodemap:
62 if deltabase not in self.nodemap:
63 raise LookupError(deltabase, self.indexfile,
63 raise LookupError(deltabase, self.indexfile,
64 _('unknown delta base'))
64 _('unknown delta base'))
65
65
66 baserev = self.rev(deltabase)
66 baserev = self.rev(deltabase)
67 # start, size, full unc. size, base (unused), link, p1, p2, node
67 # start, size, full unc. size, base (unused), link, p1, p2, node
68 e = (revlog.offset_type(start, 0), size, -1, baserev, link,
68 e = (revlog.offset_type(start, 0), size, -1, baserev, link,
69 self.rev(p1), self.rev(p2), node)
69 self.rev(p1), self.rev(p2), node)
70 self.index.insert(-1, e)
70 self.index.insert(-1, e)
71 self.nodemap[node] = n
71 self.nodemap[node] = n
72 self.bundlerevs.add(n)
72 self.bundlerevs.add(n)
73 chain = node
73 chain = node
74 n += 1
74 n += 1
75
75
76 def _chunk(self, rev):
76 def _chunk(self, rev):
77 # Warning: in case of bundle, the diff is against what we stored as
77 # Warning: in case of bundle, the diff is against what we stored as
78 # delta base, not against rev - 1
78 # delta base, not against rev - 1
79 # XXX: could use some caching
79 # XXX: could use some caching
80 if rev <= self.repotiprev:
80 if rev <= self.repotiprev:
81 return revlog.revlog._chunk(self, rev)
81 return revlog.revlog._chunk(self, rev)
82 self.bundle.seek(self.start(rev))
82 self.bundle.seek(self.start(rev))
83 return self.bundle.read(self.length(rev))
83 return self.bundle.read(self.length(rev))
84
84
85 def revdiff(self, rev1, rev2):
85 def revdiff(self, rev1, rev2):
86 """return or calculate a delta between two revisions"""
86 """return or calculate a delta between two revisions"""
87 if rev1 > self.repotiprev and rev2 > self.repotiprev:
87 if rev1 > self.repotiprev and rev2 > self.repotiprev:
88 # hot path for bundle
88 # hot path for bundle
89 revb = self.index[rev2][3]
89 revb = self.index[rev2][3]
90 if revb == rev1:
90 if revb == rev1:
91 return self._chunk(rev2)
91 return self._chunk(rev2)
92 elif rev1 <= self.repotiprev and rev2 <= self.repotiprev:
92 elif rev1 <= self.repotiprev and rev2 <= self.repotiprev:
93 return revlog.revlog.revdiff(self, rev1, rev2)
93 return revlog.revlog.revdiff(self, rev1, rev2)
94
94
95 return mdiff.textdiff(self.revision(self.node(rev1)),
95 return mdiff.textdiff(self.revision(self.node(rev1)),
96 self.revision(self.node(rev2)))
96 self.revision(self.node(rev2)))
97
97
98 def revision(self, nodeorrev):
98 def revision(self, nodeorrev):
99 """return an uncompressed revision of a given node or revision
99 """return an uncompressed revision of a given node or revision
100 number.
100 number.
101 """
101 """
102 if isinstance(nodeorrev, int):
102 if isinstance(nodeorrev, int):
103 rev = nodeorrev
103 rev = nodeorrev
104 node = self.node(rev)
104 node = self.node(rev)
105 else:
105 else:
106 node = nodeorrev
106 node = nodeorrev
107 rev = self.rev(node)
107 rev = self.rev(node)
108
108
109 if node == nullid:
109 if node == nullid:
110 return ""
110 return ""
111
111
112 text = None
112 text = None
113 chain = []
113 chain = []
114 iterrev = rev
114 iterrev = rev
115 # reconstruct the revision if it is from a changegroup
115 # reconstruct the revision if it is from a changegroup
116 while iterrev > self.repotiprev:
116 while iterrev > self.repotiprev:
117 if self._cache and self._cache[1] == iterrev:
117 if self._cache and self._cache[1] == iterrev:
118 text = self._cache[2]
118 text = self._cache[2]
119 break
119 break
120 chain.append(iterrev)
120 chain.append(iterrev)
121 iterrev = self.index[iterrev][3]
121 iterrev = self.index[iterrev][3]
122 if text is None:
122 if text is None:
123 text = self.baserevision(iterrev)
123 text = self.baserevision(iterrev)
124
124
125 while chain:
125 while chain:
126 delta = self._chunk(chain.pop())
126 delta = self._chunk(chain.pop())
127 text = mdiff.patches(text, [delta])
127 text = mdiff.patches(text, [delta])
128
128
129 self._checkhash(text, node, rev)
129 self._checkhash(text, node, rev)
130 self._cache = (node, rev, text)
130 self._cache = (node, rev, text)
131 return text
131 return text
132
132
133 def baserevision(self, nodeorrev):
133 def baserevision(self, nodeorrev):
134 # Revlog subclasses may override 'revision' method to modify format of
134 # Revlog subclasses may override 'revision' method to modify format of
135 # content retrieved from revlog. To use bundlerevlog with such class one
135 # content retrieved from revlog. To use bundlerevlog with such class one
136 # needs to override 'baserevision' and make more specific call here.
136 # needs to override 'baserevision' and make more specific call here.
137 return revlog.revlog.revision(self, nodeorrev)
137 return revlog.revlog.revision(self, nodeorrev)
138
138
139 def addrevision(self, text, transaction, link, p1=None, p2=None, d=None):
139 def addrevision(self, text, transaction, link, p1=None, p2=None, d=None):
140 raise NotImplementedError
140 raise NotImplementedError
141 def addgroup(self, revs, linkmapper, transaction):
141 def addgroup(self, revs, linkmapper, transaction):
142 raise NotImplementedError
142 raise NotImplementedError
143 def strip(self, rev, minlink):
143 def strip(self, rev, minlink):
144 raise NotImplementedError
144 raise NotImplementedError
145 def checksize(self):
145 def checksize(self):
146 raise NotImplementedError
146 raise NotImplementedError
147
147
148 class bundlechangelog(bundlerevlog, changelog.changelog):
148 class bundlechangelog(bundlerevlog, changelog.changelog):
149 def __init__(self, opener, bundle):
149 def __init__(self, opener, bundle):
150 changelog.changelog.__init__(self, opener)
150 changelog.changelog.__init__(self, opener)
151 linkmapper = lambda x: x
151 linkmapper = lambda x: x
152 bundlerevlog.__init__(self, opener, self.indexfile, bundle,
152 bundlerevlog.__init__(self, opener, self.indexfile, bundle,
153 linkmapper)
153 linkmapper)
154
154
155 def baserevision(self, nodeorrev):
155 def baserevision(self, nodeorrev):
156 # Although changelog doesn't override 'revision' method, some extensions
156 # Although changelog doesn't override 'revision' method, some extensions
157 # may replace this class with another that does. Same story with
157 # may replace this class with another that does. Same story with
158 # manifest and filelog classes.
158 # manifest and filelog classes.
159 return changelog.changelog.revision(self, nodeorrev)
159 return changelog.changelog.revision(self, nodeorrev)
160
160
161 class bundlemanifest(bundlerevlog, manifest.manifest):
161 class bundlemanifest(bundlerevlog, manifest.manifest):
162 def __init__(self, opener, bundle, linkmapper):
162 def __init__(self, opener, bundle, linkmapper):
163 manifest.manifest.__init__(self, opener)
163 manifest.manifest.__init__(self, opener)
164 bundlerevlog.__init__(self, opener, self.indexfile, bundle,
164 bundlerevlog.__init__(self, opener, self.indexfile, bundle,
165 linkmapper)
165 linkmapper)
166
166
167 def baserevision(self, nodeorrev):
167 def baserevision(self, nodeorrev):
168 return manifest.manifest.revision(self, nodeorrev)
168 return manifest.manifest.revision(self, nodeorrev)
169
169
170 class bundlefilelog(bundlerevlog, filelog.filelog):
170 class bundlefilelog(bundlerevlog, filelog.filelog):
171 def __init__(self, opener, path, bundle, linkmapper, repo):
171 def __init__(self, opener, path, bundle, linkmapper, repo):
172 filelog.filelog.__init__(self, opener, path)
172 filelog.filelog.__init__(self, opener, path)
173 bundlerevlog.__init__(self, opener, self.indexfile, bundle,
173 bundlerevlog.__init__(self, opener, self.indexfile, bundle,
174 linkmapper)
174 linkmapper)
175 self._repo = repo
175 self._repo = repo
176
176
177 def baserevision(self, nodeorrev):
177 def baserevision(self, nodeorrev):
178 return filelog.filelog.revision(self, nodeorrev)
178 return filelog.filelog.revision(self, nodeorrev)
179
179
180 def _file(self, f):
180 def _file(self, f):
181 self._repo.file(f)
181 self._repo.file(f)
182
182
183 class bundlepeer(localrepo.localpeer):
183 class bundlepeer(localrepo.localpeer):
184 def canpush(self):
184 def canpush(self):
185 return False
185 return False
186
186
187 class bundlerepository(localrepo.localrepository):
187 class bundlerepository(localrepo.localrepository):
188 def __init__(self, ui, path, bundlename):
188 def __init__(self, ui, path, bundlename):
189 self._tempparent = None
189 self._tempparent = None
190 try:
190 try:
191 localrepo.localrepository.__init__(self, ui, path)
191 localrepo.localrepository.__init__(self, ui, path)
192 except error.RepoError:
192 except error.RepoError:
193 self._tempparent = tempfile.mkdtemp()
193 self._tempparent = tempfile.mkdtemp()
194 localrepo.instance(ui, self._tempparent, 1)
194 localrepo.instance(ui, self._tempparent, 1)
195 localrepo.localrepository.__init__(self, ui, self._tempparent)
195 localrepo.localrepository.__init__(self, ui, self._tempparent)
196 self.ui.setconfig('phases', 'publish', False, 'bundlerepo')
196 self.ui.setconfig('phases', 'publish', False, 'bundlerepo')
197
197
198 if path:
198 if path:
199 self._url = 'bundle:' + util.expandpath(path) + '+' + bundlename
199 self._url = 'bundle:' + util.expandpath(path) + '+' + bundlename
200 else:
200 else:
201 self._url = 'bundle:' + bundlename
201 self._url = 'bundle:' + bundlename
202
202
203 self.tempfile = None
203 self.tempfile = None
204 f = util.posixfile(bundlename, "rb")
204 f = util.posixfile(bundlename, "rb")
205 self.bundle = exchange.readbundle(ui, f, bundlename)
205 self.bundle = exchange.readbundle(ui, f, bundlename)
206 if self.bundle.compressed():
206 if self.bundle.compressed():
207 fdtemp, temp = self.vfs.mkstemp(prefix="hg-bundle-",
207 fdtemp, temp = self.vfs.mkstemp(prefix="hg-bundle-",
208 suffix=".hg10un")
208 suffix=".hg10un")
209 self.tempfile = temp
209 self.tempfile = temp
210 fptemp = os.fdopen(fdtemp, 'wb')
210 fptemp = os.fdopen(fdtemp, 'wb')
211
211
212 try:
212 try:
213 fptemp.write("HG10UN")
213 fptemp.write("HG10UN")
214 while True:
214 while True:
215 chunk = self.bundle.read(2**18)
215 chunk = self.bundle.read(2**18)
216 if not chunk:
216 if not chunk:
217 break
217 break
218 fptemp.write(chunk)
218 fptemp.write(chunk)
219 finally:
219 finally:
220 fptemp.close()
220 fptemp.close()
221
221
222 f = self.vfs.open(self.tempfile, mode="rb")
222 f = self.vfs.open(self.tempfile, mode="rb")
223 self.bundle = exchange.readbundle(ui, f, bundlename, self.vfs)
223 self.bundle = exchange.readbundle(ui, f, bundlename, self.vfs)
224
224
225 # dict with the mapping 'filename' -> position in the bundle
225 # dict with the mapping 'filename' -> position in the bundle
226 self.bundlefilespos = {}
226 self.bundlefilespos = {}
227
227
228 @localrepo.unfilteredpropertycache
228 @localrepo.unfilteredpropertycache
229 def changelog(self):
229 def changelog(self):
230 # consume the header if it exists
230 # consume the header if it exists
231 self.bundle.changelogheader()
231 self.bundle.changelogheader()
232 c = bundlechangelog(self.sopener, self.bundle)
232 c = bundlechangelog(self.sopener, self.bundle)
233 self.manstart = self.bundle.tell()
233 self.manstart = self.bundle.tell()
234 return c
234 return c
235
235
236 @localrepo.unfilteredpropertycache
236 @localrepo.unfilteredpropertycache
237 def manifest(self):
237 def manifest(self):
238 self.bundle.seek(self.manstart)
238 self.bundle.seek(self.manstart)
239 # consume the header if it exists
239 # consume the header if it exists
240 self.bundle.manifestheader()
240 self.bundle.manifestheader()
241 m = bundlemanifest(self.sopener, self.bundle, self.changelog.rev)
241 m = bundlemanifest(self.sopener, self.bundle, self.changelog.rev)
242 self.filestart = self.bundle.tell()
242 self.filestart = self.bundle.tell()
243 return m
243 return m
244
244
245 @localrepo.unfilteredpropertycache
245 @localrepo.unfilteredpropertycache
246 def manstart(self):
246 def manstart(self):
247 self.changelog
247 self.changelog
248 return self.manstart
248 return self.manstart
249
249
250 @localrepo.unfilteredpropertycache
250 @localrepo.unfilteredpropertycache
251 def filestart(self):
251 def filestart(self):
252 self.manifest
252 self.manifest
253 return self.filestart
253 return self.filestart
254
254
255 def url(self):
255 def url(self):
256 return self._url
256 return self._url
257
257
258 def file(self, f):
258 def file(self, f):
259 if not self.bundlefilespos:
259 if not self.bundlefilespos:
260 self.bundle.seek(self.filestart)
260 self.bundle.seek(self.filestart)
261 while True:
261 while True:
262 chunkdata = self.bundle.filelogheader()
262 chunkdata = self.bundle.filelogheader()
263 if not chunkdata:
263 if not chunkdata:
264 break
264 break
265 fname = chunkdata['filename']
265 fname = chunkdata['filename']
266 self.bundlefilespos[fname] = self.bundle.tell()
266 self.bundlefilespos[fname] = self.bundle.tell()
267 while True:
267 while True:
268 c = self.bundle.deltachunk(None)
268 c = self.bundle.deltachunk(None)
269 if not c:
269 if not c:
270 break
270 break
271
271
272 if f in self.bundlefilespos:
272 if f in self.bundlefilespos:
273 self.bundle.seek(self.bundlefilespos[f])
273 self.bundle.seek(self.bundlefilespos[f])
274 return bundlefilelog(self.sopener, f, self.bundle,
274 return bundlefilelog(self.sopener, f, self.bundle,
275 self.changelog.rev, self)
275 self.changelog.rev, self)
276 else:
276 else:
277 return filelog.filelog(self.sopener, f)
277 return filelog.filelog(self.sopener, f)
278
278
279 def close(self):
279 def close(self):
280 """Close assigned bundle file immediately."""
280 """Close assigned bundle file immediately."""
281 self.bundle.close()
281 self.bundle.close()
282 if self.tempfile is not None:
282 if self.tempfile is not None:
283 self.vfs.unlink(self.tempfile)
283 self.vfs.unlink(self.tempfile)
284 if self._tempparent:
284 if self._tempparent:
285 shutil.rmtree(self._tempparent, True)
285 shutil.rmtree(self._tempparent, True)
286
286
287 def cancopy(self):
287 def cancopy(self):
288 return False
288 return False
289
289
290 def peer(self):
290 def peer(self):
291 return bundlepeer(self)
291 return bundlepeer(self)
292
292
293 def getcwd(self):
293 def getcwd(self):
294 return os.getcwd() # always outside the repo
294 return os.getcwd() # always outside the repo
295
295
296
296
297 def instance(ui, path, create):
297 def instance(ui, path, create):
298 if create:
298 if create:
299 raise util.Abort(_('cannot create new bundle repository'))
299 raise util.Abort(_('cannot create new bundle repository'))
300 parentpath = ui.config("bundle", "mainreporoot", "")
300 parentpath = ui.config("bundle", "mainreporoot", "")
301 if not parentpath:
301 if not parentpath:
302 # try to find the correct path to the working directory repo
302 # try to find the correct path to the working directory repo
303 parentpath = cmdutil.findrepo(os.getcwd())
303 parentpath = cmdutil.findrepo(os.getcwd())
304 if parentpath is None:
304 if parentpath is None:
305 parentpath = ''
305 parentpath = ''
306 if parentpath:
306 if parentpath:
307 # Try to make the full path relative so we get a nice, short URL.
307 # Try to make the full path relative so we get a nice, short URL.
308 # In particular, we don't want temp dir names in test outputs.
308 # In particular, we don't want temp dir names in test outputs.
309 cwd = os.getcwd()
309 cwd = os.getcwd()
310 if parentpath == cwd:
310 if parentpath == cwd:
311 parentpath = ''
311 parentpath = ''
312 else:
312 else:
313 cwd = os.path.join(cwd,'')
313 cwd = os.path.join(cwd,'')
314 if parentpath.startswith(cwd):
314 if parentpath.startswith(cwd):
315 parentpath = parentpath[len(cwd):]
315 parentpath = parentpath[len(cwd):]
316 u = util.url(path)
316 u = util.url(path)
317 path = u.localpath()
317 path = u.localpath()
318 if u.scheme == 'bundle':
318 if u.scheme == 'bundle':
319 s = path.split("+", 1)
319 s = path.split("+", 1)
320 if len(s) == 1:
320 if len(s) == 1:
321 repopath, bundlename = parentpath, s[0]
321 repopath, bundlename = parentpath, s[0]
322 else:
322 else:
323 repopath, bundlename = s
323 repopath, bundlename = s
324 else:
324 else:
325 repopath, bundlename = parentpath, path
325 repopath, bundlename = parentpath, path
326 return bundlerepository(ui, repopath, bundlename)
326 return bundlerepository(ui, repopath, bundlename)
327
327
328 def getremotechanges(ui, repo, other, onlyheads=None, bundlename=None,
328 def getremotechanges(ui, repo, other, onlyheads=None, bundlename=None,
329 force=False):
329 force=False):
330 '''obtains a bundle of changes incoming from other
330 '''obtains a bundle of changes incoming from other
331
331
332 "onlyheads" restricts the returned changes to those reachable from the
332 "onlyheads" restricts the returned changes to those reachable from the
333 specified heads.
333 specified heads.
334 "bundlename", if given, stores the bundle to this file path permanently;
334 "bundlename", if given, stores the bundle to this file path permanently;
335 otherwise it's stored to a temp file and gets deleted again when you call
335 otherwise it's stored to a temp file and gets deleted again when you call
336 the returned "cleanupfn".
336 the returned "cleanupfn".
337 "force" indicates whether to proceed on unrelated repos.
337 "force" indicates whether to proceed on unrelated repos.
338
338
339 Returns a tuple (local, csets, cleanupfn):
339 Returns a tuple (local, csets, cleanupfn):
340
340
341 "local" is a local repo from which to obtain the actual incoming
341 "local" is a local repo from which to obtain the actual incoming
342 changesets; it is a bundlerepo for the obtained bundle when the
342 changesets; it is a bundlerepo for the obtained bundle when the
343 original "other" is remote.
343 original "other" is remote.
344 "csets" lists the incoming changeset node ids.
344 "csets" lists the incoming changeset node ids.
345 "cleanupfn" must be called without arguments when you're done processing
345 "cleanupfn" must be called without arguments when you're done processing
346 the changes; it closes both the original "other" and the one returned
346 the changes; it closes both the original "other" and the one returned
347 here.
347 here.
348 '''
348 '''
349 tmp = discovery.findcommonincoming(repo, other, heads=onlyheads,
349 tmp = discovery.findcommonincoming(repo, other, heads=onlyheads,
350 force=force)
350 force=force)
351 common, incoming, rheads = tmp
351 common, incoming, rheads = tmp
352 if not incoming:
352 if not incoming:
353 try:
353 try:
354 if bundlename:
354 if bundlename:
355 repo.vfs.unlink(bundlename)
355 os.unlink(bundlename)
356 except OSError:
356 except OSError:
357 pass
357 pass
358 return repo, [], other.close
358 return repo, [], other.close
359
359
360 bundle = None
360 bundle = None
361 bundlerepo = None
361 bundlerepo = None
362 localrepo = other.local()
362 localrepo = other.local()
363 if bundlename or not localrepo:
363 if bundlename or not localrepo:
364 # create a bundle (uncompressed if other repo is not local)
364 # create a bundle (uncompressed if other repo is not local)
365
365
366 if other.capable('getbundle'):
366 if other.capable('getbundle'):
367 cg = other.getbundle('incoming', common=common, heads=rheads)
367 cg = other.getbundle('incoming', common=common, heads=rheads)
368 elif onlyheads is None and not other.capable('changegroupsubset'):
368 elif onlyheads is None and not other.capable('changegroupsubset'):
369 # compat with older servers when pulling all remote heads
369 # compat with older servers when pulling all remote heads
370 cg = other.changegroup(incoming, "incoming")
370 cg = other.changegroup(incoming, "incoming")
371 rheads = None
371 rheads = None
372 else:
372 else:
373 cg = other.changegroupsubset(incoming, rheads, 'incoming')
373 cg = other.changegroupsubset(incoming, rheads, 'incoming')
374 bundletype = localrepo and "HG10BZ" or "HG10UN"
374 bundletype = localrepo and "HG10BZ" or "HG10UN"
375 fname = bundle = changegroup.writebundle(cg, bundlename, bundletype)
375 fname = bundle = changegroup.writebundle(cg, bundlename, bundletype)
376 # keep written bundle?
376 # keep written bundle?
377 if bundlename:
377 if bundlename:
378 bundle = None
378 bundle = None
379 if not localrepo:
379 if not localrepo:
380 # use the created uncompressed bundlerepo
380 # use the created uncompressed bundlerepo
381 localrepo = bundlerepo = bundlerepository(repo.baseui, repo.root,
381 localrepo = bundlerepo = bundlerepository(repo.baseui, repo.root,
382 fname)
382 fname)
383 # this repo contains local and other now, so filter out local again
383 # this repo contains local and other now, so filter out local again
384 common = repo.heads()
384 common = repo.heads()
385 if localrepo:
385 if localrepo:
386 # Part of common may be remotely filtered
386 # Part of common may be remotely filtered
387 # So use an unfiltered version
387 # So use an unfiltered version
388 # The discovery process probably need cleanup to avoid that
388 # The discovery process probably need cleanup to avoid that
389 localrepo = localrepo.unfiltered()
389 localrepo = localrepo.unfiltered()
390
390
391 csets = localrepo.changelog.findmissing(common, rheads)
391 csets = localrepo.changelog.findmissing(common, rheads)
392
392
393 def cleanup():
393 def cleanup():
394 if bundlerepo:
394 if bundlerepo:
395 bundlerepo.close()
395 bundlerepo.close()
396 if bundle:
396 if bundle:
397 repo.vfs.unlink(bundle)
397 os.unlink(bundle)
398 other.close()
398 other.close()
399
399
400 return (localrepo, csets, cleanup)
400 return (localrepo, csets, cleanup)
General Comments 0
You need to be logged in to leave comments. Login now