comparison mercurial/localrepo.py @ 1981:736b6c96bbbc

make incoming work via ssh (issue139); move chunk code into separate module. Incoming ssh needs to detect the end of the changegroup, otherwise it would block trying to read from the ssh pipe. This is done by parsing the changegroup chunks. bundlerepo.getchunk() already is identical to localrepo.addchangegroup.getchunk(), which is followed by getgroup which looks much like what you can re-use in bundlerepository.__init__() and in write_bundle(). bundlerevlog.__init__.genchunk() looks very similar, too, as do some while loops in localrepo.py. Applied patch from Benoit Boissinot to move duplicate/related code to mercurial/changegroup.py and use this to fix incoming ssh.
author Thomas Arendsen Hein <thomas@intevation.de>
date Tue, 21 Mar 2006 11:47:21 +0100
parents 72f7a335b955
children ae12a81549a7
comparison
equal deleted inserted replaced
1980:dfb796786337 1981:736b6c96bbbc
3 # Copyright 2005 Matt Mackall <mpm@selenic.com> 3 # Copyright 2005 Matt Mackall <mpm@selenic.com>
4 # 4 #
5 # This software may be used and distributed according to the terms 5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference. 6 # of the GNU General Public License, incorporated herein by reference.
7 7
8 import struct, os, util 8 import os, util
9 import filelog, manifest, changelog, dirstate, repo 9 import filelog, manifest, changelog, dirstate, repo
10 from node import * 10 from node import *
11 from i18n import gettext as _ 11 from i18n import gettext as _
12 from demandload import * 12 from demandload import *
13 demandload(globals(), "re lock transaction tempfile stat mdiff errno ui") 13 demandload(globals(), "re lock transaction tempfile stat mdiff errno ui")
14 demandload(globals(), "changegroup")
14 15
15 class localrepository(object): 16 class localrepository(object):
16 def __del__(self): 17 def __del__(self):
17 self.transhandle = None 18 self.transhandle = None
18 def __init__(self, parentui, path=None, create=0): 19 def __init__(self, parentui, path=None, create=0):
1242 else: 1243 else:
1243 msng_filenode_lst = [] 1244 msng_filenode_lst = []
1244 # If any filenodes are left, generate the group for them, 1245 # If any filenodes are left, generate the group for them,
1245 # otherwise don't bother. 1246 # otherwise don't bother.
1246 if len(msng_filenode_lst) > 0: 1247 if len(msng_filenode_lst) > 0:
1247 yield struct.pack(">l", len(fname) + 4) + fname 1248 yield changegroup.genchunk(fname)
1248 # Sort the filenodes by their revision # 1249 # Sort the filenodes by their revision #
1249 msng_filenode_lst.sort(cmp_by_rev_func(filerevlog)) 1250 msng_filenode_lst.sort(cmp_by_rev_func(filerevlog))
1250 # Create a group generator and only pass in a changenode 1251 # Create a group generator and only pass in a changenode
1251 # lookup function as we need to collect no information 1252 # lookup function as we need to collect no information
1252 # from filenodes. 1253 # from filenodes.
1256 yield chnk 1257 yield chnk
1257 if msng_filenode_set.has_key(fname): 1258 if msng_filenode_set.has_key(fname):
1258 # Don't need this anymore, toss it to free memory. 1259 # Don't need this anymore, toss it to free memory.
1259 del msng_filenode_set[fname] 1260 del msng_filenode_set[fname]
1260 # Signal that no more groups are left. 1261 # Signal that no more groups are left.
1261 yield struct.pack(">l", 0) 1262 yield changegroup.closechunk()
1262 1263
1263 self.hook('outgoing', node=hex(msng_cl_lst[0]), source=source) 1264 self.hook('outgoing', node=hex(msng_cl_lst[0]), source=source)
1264 1265
1265 return util.chunkbuffer(gengroup()) 1266 return util.chunkbuffer(gengroup())
1266 1267
1316 for fname in changedfiles: 1317 for fname in changedfiles:
1317 filerevlog = self.file(fname) 1318 filerevlog = self.file(fname)
1318 nodeiter = gennodelst(filerevlog) 1319 nodeiter = gennodelst(filerevlog)
1319 nodeiter = list(nodeiter) 1320 nodeiter = list(nodeiter)
1320 if nodeiter: 1321 if nodeiter:
1321 yield struct.pack(">l", len(fname) + 4) + fname 1322 yield changegroup.genchunk(fname)
1322 lookup = lookuprevlink_func(filerevlog) 1323 lookup = lookuprevlink_func(filerevlog)
1323 for chnk in filerevlog.group(nodeiter, lookup): 1324 for chnk in filerevlog.group(nodeiter, lookup):
1324 yield chnk 1325 yield chnk
1325 1326
1326 yield struct.pack(">l", 0) 1327 yield changegroup.closechunk()
1327 self.hook('outgoing', node=hex(nodes[0]), source=source) 1328 self.hook('outgoing', node=hex(nodes[0]), source=source)
1328 1329
1329 return util.chunkbuffer(gengroup()) 1330 return util.chunkbuffer(gengroup())
1330 1331
1331 def addchangegroup(self, source): 1332 def addchangegroup(self, source):
1332
1333 def getchunk():
1334 d = source.read(4)
1335 if not d:
1336 return ""
1337 l = struct.unpack(">l", d)[0]
1338 if l <= 4:
1339 return ""
1340 d = source.read(l - 4)
1341 if len(d) < l - 4:
1342 raise repo.RepoError(_("premature EOF reading chunk"
1343 " (got %d bytes, expected %d)")
1344 % (len(d), l - 4))
1345 return d
1346
1347 def getgroup():
1348 while 1:
1349 c = getchunk()
1350 if not c:
1351 break
1352 yield c
1353 1333
1354 def csmap(x): 1334 def csmap(x):
1355 self.ui.debug(_("add changeset %s\n") % short(x)) 1335 self.ui.debug(_("add changeset %s\n") % short(x))
1356 return self.changelog.count() 1336 return self.changelog.count()
1357 1337
1370 oldheads = len(self.changelog.heads()) 1350 oldheads = len(self.changelog.heads())
1371 1351
1372 # pull off the changeset group 1352 # pull off the changeset group
1373 self.ui.status(_("adding changesets\n")) 1353 self.ui.status(_("adding changesets\n"))
1374 co = self.changelog.tip() 1354 co = self.changelog.tip()
1375 cn = self.changelog.addgroup(getgroup(), csmap, tr, 1) # unique 1355 chunkiter = changegroup.chunkiter(source)
1356 cn = self.changelog.addgroup(chunkiter, csmap, tr, 1) # unique
1376 cnr, cor = map(self.changelog.rev, (cn, co)) 1357 cnr, cor = map(self.changelog.rev, (cn, co))
1377 if cn == nullid: 1358 if cn == nullid:
1378 cnr = cor 1359 cnr = cor
1379 changesets = cnr - cor 1360 changesets = cnr - cor
1380 1361
1381 # pull off the manifest group 1362 # pull off the manifest group
1382 self.ui.status(_("adding manifests\n")) 1363 self.ui.status(_("adding manifests\n"))
1383 mm = self.manifest.tip() 1364 mm = self.manifest.tip()
1384 mo = self.manifest.addgroup(getgroup(), revmap, tr) 1365 chunkiter = changegroup.chunkiter(source)
1366 mo = self.manifest.addgroup(chunkiter, revmap, tr)
1385 1367
1386 # process the files 1368 # process the files
1387 self.ui.status(_("adding file changes\n")) 1369 self.ui.status(_("adding file changes\n"))
1388 while 1: 1370 while 1:
1389 f = getchunk() 1371 f = changegroup.getchunk(source)
1390 if not f: 1372 if not f:
1391 break 1373 break
1392 self.ui.debug(_("adding %s revisions\n") % f) 1374 self.ui.debug(_("adding %s revisions\n") % f)
1393 fl = self.file(f) 1375 fl = self.file(f)
1394 o = fl.count() 1376 o = fl.count()
1395 n = fl.addgroup(getgroup(), revmap, tr) 1377 chunkiter = changegroup.chunkiter(source)
1378 n = fl.addgroup(chunkiter, revmap, tr)
1396 revisions += fl.count() - o 1379 revisions += fl.count() - o
1397 files += 1 1380 files += 1
1398 1381
1399 newheads = len(self.changelog.heads()) 1382 newheads = len(self.changelog.heads())
1400 heads = "" 1383 heads = ""