Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/subrepo.py @ 51879:3b8d92f71d92
archive: defer opening the output until a file is matched
Before, if no file is matched, an error is thrown, but the archive is
created anyway. When using hgweb, an error 500 is returned as the
response body already exists when the error is seen.
Afterwards, the archive is created before the first match is emitted.
If no match is found, no archive is created. This is more consistent
behavior as an empty archive is not a representable in all output
formats, e.g. tar archives.
author | Joerg Sonnenberger <joerg@bec.de> |
---|---|
date | Wed, 15 Nov 2023 22:11:34 +0100 |
parents | a1e4fa9330d8 |
children | f4733654f144 |
comparison
equal
deleted
inserted
replaced
51878:7933bcb02bfc | 51879:3b8d92f71d92 |
---|---|
361 | 361 |
362 def printfiles(self, ui, m, uipathfn, fm, fmt, subrepos): | 362 def printfiles(self, ui, m, uipathfn, fm, fmt, subrepos): |
363 """handle the files command for this subrepo""" | 363 """handle the files command for this subrepo""" |
364 return 1 | 364 return 1 |
365 | 365 |
366 def archive( | 366 def archive(self, opener, prefix, match: matchmod.basematcher, decode=True): |
367 self, archiver, prefix, match: matchmod.basematcher, decode=True | |
368 ): | |
369 files = [f for f in self.files() if match(f)] | 367 files = [f for f in self.files() if match(f)] |
370 total = len(files) | 368 total = len(files) |
371 relpath = subrelpath(self) | 369 relpath = subrelpath(self) |
372 progress = self.ui.makeprogress( | 370 progress = self.ui.makeprogress( |
373 _(b'archiving (%s)') % relpath, unit=_(b'files'), total=total | 371 _(b'archiving (%s)') % relpath, unit=_(b'files'), total=total |
374 ) | 372 ) |
375 progress.update(0) | 373 progress.update(0) |
374 archiver = None | |
376 for name in files: | 375 for name in files: |
377 flags = self.fileflags(name) | 376 flags = self.fileflags(name) |
378 mode = b'x' in flags and 0o755 or 0o644 | 377 mode = b'x' in flags and 0o755 or 0o644 |
379 symlink = b'l' in flags | 378 symlink = b'l' in flags |
379 if archiver is None: | |
380 archiver = opener() | |
380 archiver.addfile( | 381 archiver.addfile( |
381 prefix + name, mode, symlink, self.filedata(name, decode) | 382 prefix + name, mode, symlink, self.filedata(name, decode) |
382 ) | 383 ) |
383 progress.increment() | 384 progress.increment() |
384 progress.complete() | 385 progress.complete() |
649 _(b'warning: error "%s" in subrepository "%s"\n') | 650 _(b'warning: error "%s" in subrepository "%s"\n') |
650 % (inst, subrelpath(self)) | 651 % (inst, subrelpath(self)) |
651 ) | 652 ) |
652 | 653 |
653 @annotatesubrepoerror | 654 @annotatesubrepoerror |
654 def archive( | 655 def archive(self, opener, prefix, match: matchmod.basematcher, decode=True): |
655 self, archiver, prefix, match: matchmod.basematcher, decode=True | |
656 ): | |
657 self._get(self._state + (b'hg',)) | 656 self._get(self._state + (b'hg',)) |
658 files = [f for f in self.files() if match(f)] | 657 files = [f for f in self.files() if match(f)] |
659 rev = self._state[1] | 658 rev = self._state[1] |
660 ctx = self._repo[rev] | 659 ctx = self._repo[rev] |
661 scmutil.prefetchfiles( | 660 scmutil.prefetchfiles( |
662 self._repo, [(ctx.rev(), scmutil.matchfiles(self._repo, files))] | 661 self._repo, [(ctx.rev(), scmutil.matchfiles(self._repo, files))] |
663 ) | 662 ) |
664 total = abstractsubrepo.archive(self, archiver, prefix, match) | 663 total = abstractsubrepo.archive(self, opener, prefix, match) |
665 for subpath in ctx.substate: | 664 for subpath in ctx.substate: |
666 s = subrepo(ctx, subpath, True) | 665 s = subrepo(ctx, subpath, True) |
667 submatch = matchmod.subdirmatcher(subpath, match) | 666 submatch = matchmod.subdirmatcher(subpath, match) |
668 subprefix = prefix + subpath + b'/' | 667 subprefix = prefix + subpath + b'/' |
669 total += s.archive(archiver, subprefix, submatch, decode) | 668 total += s.archive(opener, subprefix, submatch, decode) |
670 return total | 669 return total |
671 | 670 |
672 @annotatesubrepoerror | 671 @annotatesubrepoerror |
673 def dirty(self, ignoreupdate=False, missing=False): | 672 def dirty(self, ignoreupdate=False, missing=False): |
674 r = self._state[1] | 673 r = self._state[1] |
1908 if kind == stat.S_IFDIR: | 1907 if kind == stat.S_IFDIR: |
1909 self.wvfs.rmtree(f) | 1908 self.wvfs.rmtree(f) |
1910 else: | 1909 else: |
1911 self.wvfs.unlink(f) | 1910 self.wvfs.unlink(f) |
1912 | 1911 |
1913 def archive( | 1912 def archive(self, opener, prefix, match: matchmod.basematcher, decode=True): |
1914 self, archiver, prefix, match: matchmod.basematcher, decode=True | |
1915 ): | |
1916 total = 0 | 1913 total = 0 |
1917 source, revision = self._state | 1914 source, revision = self._state |
1918 if not revision: | 1915 if not revision: |
1919 return total | 1916 return total |
1920 self._fetch(source, revision) | 1917 self._fetch(source, revision) |
1926 tar = tarfile.open(fileobj=tarstream, mode='r|') | 1923 tar = tarfile.open(fileobj=tarstream, mode='r|') |
1927 relpath = subrelpath(self) | 1924 relpath = subrelpath(self) |
1928 progress = self.ui.makeprogress( | 1925 progress = self.ui.makeprogress( |
1929 _(b'archiving (%s)') % relpath, unit=_(b'files') | 1926 _(b'archiving (%s)') % relpath, unit=_(b'files') |
1930 ) | 1927 ) |
1928 archiver = None | |
1931 progress.update(0) | 1929 progress.update(0) |
1932 for info in tar: | 1930 for info in tar: |
1933 if info.isdir(): | 1931 if info.isdir(): |
1934 continue | 1932 continue |
1935 bname = pycompat.fsencode(info.name) | 1933 bname = pycompat.fsencode(info.name) |
1942 if f: | 1940 if f: |
1943 data = f.read() | 1941 data = f.read() |
1944 else: | 1942 else: |
1945 self.ui.warn(_(b'skipping "%s" (unknown type)') % bname) | 1943 self.ui.warn(_(b'skipping "%s" (unknown type)') % bname) |
1946 continue | 1944 continue |
1945 if archiver is None: | |
1946 archiver = opener() | |
1947 archiver.addfile(prefix + bname, info.mode, info.issym(), data) | 1947 archiver.addfile(prefix + bname, info.mode, info.issym(), data) |
1948 total += 1 | 1948 total += 1 |
1949 progress.increment() | 1949 progress.increment() |
1950 progress.complete() | 1950 progress.complete() |
1951 return total | 1951 return total |