Как предложил Мартин, я написал свое собственное расширение. Я опубликую код здесь, в надежде, что кто-то улучшит его или сделает его доступным по умолчанию в Mercurial ...
Спасибо, Мартин, я основал его на вашем расширении onsub, и да, я знаю, что есть несколько проблем с ним, но пока он служит своей цели. (проблемы с более чем 10 подпунктами и более 1 уровня вложенности)
"""execute the Bundle command in a repository and each subrepository"""
# bundlesb.py - execute the Bundle command in a repository and each subrepository
#
# Copyright 2012 Johan G.
#
# This software may be used and distributed according to the terms of
# the GNU General Public License version 2 or any later version.
import os
import zipfile
from mercurial.i18n import _
from mercurial import extensions, subrepo, util
def bundlesb(ui, repo, *args, **opts):
"""execute the Bundle command in a repository and each subrepository
Creates a combined bundle (with hgs extention) for the current
repository.
Because the revision numbers of the root and the subrepos will differ,
we cannot reliably choose a revision to start from. A date to start
from should be nice, but i have not taken the time to implement this.
Instead i choose to take the N (default=10) last changesets into account.
This seems to work well in our environment. Instead of providing the
number of changesets for the operation, you can also specify -a to
include all changesets.
Use --verbose/-v to print information and the subrepo
name for each subrepo.
"""
ui.status("Starting operation\n")
zipname = os.path.splitext(' '.join(args))[0]
if (zipname==''):
zipname = os.path.join(repo.root, os.path.split(repo.root)[1])
#raise ValueError("FILE cannot be empty")
zipname= zipname + '.hgs'
allchangesets=opts.get('all')
changesets=opts.get('changesets')
ui.debug(_("input filename=%s ; AllChangesets=%s ; Changesets=%s \n") % (zipname, allchangesets, changesets))
files=[]
#work on the root repository
runcmd(ui, repo.root, files, "0Root", repo['.'].rev(), ".", changesets, allchangesets)
#do the same for each subrepository
foreach(ui, repo, files, changesets, allchangesets)
# open the zip file for writing, and write stuff to it
ui.status("creating file: " + zipname + "\n\n")
file = zipfile.ZipFile(zipname, "w" )
for name in files:
file.write(name, os.path.basename(name), zipfile.ZIP_DEFLATED)
file.close()
# open the file again, to see what's in it
file = zipfile.ZipFile(zipname, "r")
for info in file.infolist():
ui.debug(info.filename + " " + str(info.date_time) + " " + str(info.file_size) + " " + str(info.compress_size) +"\n")
#delete all the compressed .hg files
os.remove(os.path.join(repo.root, info.filename))
ui.status("\nOperation complete\n")
def foreach(ui, repo, files, changesets, allchangesets):
ctx = repo['.']
work = [(1, ctx.sub(subpath)) for subpath in sorted(ctx.substate)]
while work:
(depth, sub) = work.pop(0)
if hasattr(subrepo, 'relpath'):
relpath = subrepo.relpath(sub)
else:
relpath = subrepo.subrelpath(sub)
rev=sub._repo[sub._state[1]].rev()
ui.debug(str(rev) + " " + str(sub._repo[sub._state[1]].user()) + " " + str(sub._repo[sub._state[1]].date()) + "\n")
if depth>1:
raise Exception("No support for nested levels deeper than 1 yet.")
runcmd(ui, repo.root, files, str(depth) + relpath, rev, relpath, changesets, allchangesets)
if isinstance(sub, subrepo.hgsubrepo):
rev = sub._state[1]
ctx = sub._repo[rev]
w = [(depth + 1, ctx.sub(subpath))
for subpath in sorted(ctx.substate)]
work.extend(w)
def runcmd(ui, root, files, name, revision, path, changesets, allchangesets):
files.append(root + "/" + name + ".hg")
if (revision<=changesets) or allchangesets:
cmd="hg bundle -a " + root + "/" + name + ".hg"
else:
cmd="hg bundle --base " + str(revision-changesets)+ " " + root + "/" + name + ".hg"
ui.note(_("Working on '%s' in %s\n") % (path, root))
ui.debug( "command line: "+ cmd +"\n")
util.system(cmd,
cwd=os.path.join(root, path),
onerr=util.Abort,
errprefix=_('terminated bundlesub in %s') % path)
cmdtable = {
"bundlesb":
(bundlesb,
[('c', 'changesets', 10, _('the number of recent changesets to include in the bundle'), 'N'),
('a', 'all', None, _('include all changesets in the bundle')),],
_('[-c|-a] FILE...'))
}
И наоборот:
"""execute the UnBundle command in a repository and each subrepository
for a file created with BundleSb"""
# unbundlesub.py - execute the UnBundle command in a repository and each subrepository
#
# Copyright 2012 Johan G.
#
# This software may be used and distributed according to the terms of
# the GNU General Public License version 2 or any later version.
import os
import zipfile
#import glob
from mercurial.i18n import _
from mercurial import extensions, subrepo, util
def unbundlesb(ui, repo, *args, **opts):
"""execute the UnBundle command in a repository and each subrepository
for a file created with BundleSb
Updates the current repository from a combined bundle (with hgs extention).
Use --verbose/-v to print more detailed information during the operation.
"""
ui.status("Starting unbundle operation\n")
update = opts.get('update')
file = os.path.splitext(' '.join(args))[0] + '.hgs'
if (file==''):
raise ValueError("FILE cannot be empty")
ui.debug("input filename=" + file + "\n")
zfile = zipfile.ZipFile(file, "r" )
for info in zfile.infolist():
ui.debug(info.filename + " " + str(info.date_time) + " " + str(info.file_size) + " " + str(info.compress_size) +"\n")
zfile.extract(info,repo.root)
runcmd(ui, repo.root, info.filename, update)
#delete all the compressed .hg files
os.remove(os.path.join(repo.root, info.filename))
zfile.close()
ui.status("\nOperation complete\n")
def runcmd(ui, root, name, update):
level=name[0]
rep=name[1:len(name)-3]
ui.debug(_("Detected level=%s for repository %s \n") % (level, rep))
cmd="hg unbundle "
if (update): cmd= cmd + "-u "
cmd= cmd + root + "\\" + name
ui.note(_("Working on '%s' in %s\n") % (rep, root))
if (level == '1'):
wd=os.path.join(root, rep)
elif (level=='0'):
wd=root
else:
raise Exception("Do not know what to do with a level >1")
ui.debug(_("command line: %s in working directory %s\n") % (cmd, wd))
util.system(cmd,
cwd=wd,
onerr=util.Abort,
errprefix=_('terminated unbundlesub in %s') % rep)
cmdtable = {
"unbundlesb":
(unbundlesb,
[('u', 'update', None,
_('update to new branch head if changesets were unbundled'))],
_('[-u] FILE...'))
}