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