My experiences with Mercurial
Brendan Cully
brendan at kublai.com
Sun Jun 17 22:39:52 UTC 2007
On Sunday, 17 June 2007 at 18:38, mirza wrote:
> Hi,
> > So really what we need is a simple & secure way for the users
> > (developers in this case) to share their changesets. "hg serve" seems
> > to fit the definition of simple but not secure. The trouble of
> > setting up IIS/Apache and configuring SSL or setting up ssh servers
> > on each developer's machine (win & unix) outweighs the benefits of
> > using mercurial. We were mainly looking to remove the need for the
> > central server.
>
> I had this problem too, so I proposed exchanging bundles via email/ftp
> with --create-digest option. It is Issue 392 now and I don't have idea
> when/if it will be implemented. That would certainly solve problem for
> all those people that doesn't want even to _think_ about setting up
> Apache for this (sounds sooooo undistributed to me).
Something like that doesn't sound too tricky. Here's a prototype
extension I knocked up a few minutes ago. From 'hg help digest' with
the extension loaded:
hg digest FILE
Create a digest of the repository
A digest is a small file containing a summary of the nodes in the
repository. It may be used with outgoing or bundle in other repositories.
The digest will be written into FILE.
Example usage:
cd repo1
hg digest ../repo1.digest
cd ../repo2
hg bundle ../to-repo1.hg digest://../repo1.digest
I can't say it's particularly well tested though.
-------------- next part --------------
# Copyright (C) 2007 Brendan Cully <brendan at kublai.com>
# Published under the GNU GPL
'''digest extension'''
from mercurial.node import *
from mercurial.i18n import _
from mercurial import cmdutil, hg, remoterepo, revlog, util
import sys
class digestrepo(remoterepo.remoterepository):
"Representation of a repository via a digest of its changelog nodes"
SIGNATURE = 'HDDGGZ'
def __init__(self, ui, path):
self.nodes = []
self.ui = ui
self.path = path
if path:
self.read(path)
def loadchangelog(self, changelog):
self.nodes = [changelog.node(i) for i in xrange(changelog.count())]
def write(self, filename):
def chunknodes(nodes):
CHUNKSIZE = 4096
start = 0
l = len(nodes)
while start < l:
yield ''.join(nodes[start:start+CHUNKSIZE])
start += CHUNKSIZE
fd = file(filename, "wb")
fd.write(self.SIGNATURE)
for i in chunknodes(self.nodes):
fd.write(i)
fd.close()
def read(self, filename):
def chunkstream(stream):
start = 0
l = len(stream)
while start < l:
yield stream[start:start+20]
start += 20
fd = file(filename, "rb")
hdr = fd.read(6)
if hdr != self.SIGNATURE:
raise util.Abort("The digest file is not in a recognized format")
nodes = []
for n in chunkstream(fd.read()):
nodes.append(n)
self.nodes = nodes
def dump(self):
for n in self.nodes:
print hex(n)
def digest(ui, repo, filename):
'''Create a digest of the repository
A digest is a small file containing a summary of the nodes in the
repository. It may be used with outgoing or bundle in other repositories.
The digest will be written into FILE.
Example usage:
cd repo1
hg digest ../repo1.digest
cd ../repo2
hg bundle ../to-repo1.hg digest://../repo1.digest
'''
d = digestrepo(ui, None)
d.loadchangelog(repo.changelog)
d.write(filename)
def reposetup(ui, repo):
def addscheme(name, mod):
hg.schemes[name] = mod
class monkeyrepo(repo.__class__):
def findoutgoing(self, remote, base=None, heads=None, force=False):
remotedigest = isinstance(remote, digestrepo)
if not base and remotedigest:
base = {}
parents = {}
for n in remote.nodes:
try:
i = self.changelog.rev(n)
base[n] = 1
except revlog.LookupError:
pass
s = super(monkeyrepo, self)
return s.findoutgoing(remote, base=base, heads=heads, force=force)
addscheme('digest', sys.modules[__name__])
if repo.local():
repo.__class__ = monkeyrepo
def instance(ui, path, create):
if create:
raise util.Abort(_('cannot create new digest repository'))
return digestrepo(ui, util.drop_scheme('digest', path))
cmdtable = {
'digest': (digest, [], "hg digest FILE")
}
More information about the Mercurial
mailing list