diff --git a/mercurial/archival.py b/mercurial/archival.py --- a/mercurial/archival.py +++ b/mercurial/archival.py @@ -205,7 +205,7 @@ archivers = { } def archive(repo, dest, node, kind, decode=True, matchfn=None, - prefix=None, mtime=None): + prefix=None, mtime=None, subrepos=False): '''create archive of repo as it was at node. dest can be name of directory, name of archive file, or file @@ -263,4 +263,10 @@ def archive(repo, dest, node, kind, deco for f in ctx: ff = ctx.flags(f) write(f, 'x' in ff and 0755 or 0644, 'l' in ff, ctx[f].data) + + if subrepos: + for subpath in ctx.substate: + sub = ctx.sub(subpath) + sub.archive(archiver, prefix) + archiver.done() diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -199,7 +199,7 @@ def archive(ui, repo, dest, **opts): prefix = cmdutil.make_filename(repo, prefix, node) matchfn = cmdutil.match(repo, [], opts) archival.archive(repo, dest, node, kind, not opts.get('no_decode'), - matchfn, prefix) + matchfn, prefix, subrepos=opts.get('subrepos')) def backout(ui, repo, node=None, rev=None, **opts): '''reverse effect of earlier changeset @@ -3963,7 +3963,7 @@ table = { _('revision to distribute'), _('REV')), ('t', 'type', '', _('type of distribution to create'), _('TYPE')), - ] + walkopts, + ] + subrepoopts + walkopts, _('[OPTION]... DEST')), "backout": (backout, diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py --- a/mercurial/subrepo.py +++ b/mercurial/subrepo.py @@ -282,6 +282,15 @@ class abstractsubrepo(object): """return file flags""" return '' + def archive(self, archiver, prefix): + for name in self.files(): + flags = self.fileflags(name) + mode = 'x' in flags and 0755 or 0644 + symlink = 'l' in flags + archiver.addfile(os.path.join(prefix, self._path, name), + mode, symlink, self.filedata(name)) + + class hgsubrepo(abstractsubrepo): def __init__(self, ctx, path, state): self._path = path @@ -341,6 +350,15 @@ class hgsubrepo(abstractsubrepo): self._repo.ui.warn(_("warning: %s in %s\n") % (inst, relpath(self))) + def archive(self, archiver, prefix): + abstractsubrepo.archive(self, archiver, prefix) + + rev = self._state[1] + ctx = self._repo[rev] + for subpath in ctx.substate: + s = subrepo(ctx, subpath) + s.archive(archiver, os.path.join(prefix, self._path)) + def dirty(self): r = self._state[1] if r == '': diff --git a/tests/test-subrepo-recursion.t b/tests/test-subrepo-recursion.t --- a/tests/test-subrepo-recursion.t +++ b/tests/test-subrepo-recursion.t @@ -227,6 +227,40 @@ Status between revisions: z1 +z2 +Test archiving to a directory tree: + + $ hg archive --subrepos ../archive + $ find ../archive + ../archive + ../archive/foo + ../archive/foo/bar + ../archive/foo/bar/z.txt + ../archive/foo/.hgsubstate + ../archive/foo/.hgsub + ../archive/foo/y.txt + ../archive/x.txt + ../archive/.hgsubstate + ../archive/.hgsub + ../archive/.hg_archival.txt + +Test archiving to zip file: + + $ hg archive --subrepos ../archive.zip + $ unzip -l ../archive.zip + Archive: ../archive.zip + Length Date Time Name + --------- ---------- ----- ---- + 147 1980-01-01 00:00 archive/.hg_archival.txt + 10 1980-01-01 00:00 archive/.hgsub + 45 1980-01-01 00:00 archive/.hgsubstate + 3 1980-01-01 00:00 archive/x.txt + 9 1980-01-01 00:00 archive/foo/y.txt + 10 1980-01-01 00:00 archive/foo/.hgsub + 45 1980-01-01 00:00 archive/foo/.hgsubstate + 9 1980-01-01 00:00 archive/foo/bar/z.txt + --------- ------- + 278 8 files + Clone and test outgoing: $ cd ..