204 |
204 |
205 auto-generation of clone bundles |
205 auto-generation of clone bundles |
206 -------------------------------- |
206 -------------------------------- |
207 |
207 |
208 It is possible to set Mercurial to automatically re-generate clone bundles when |
208 It is possible to set Mercurial to automatically re-generate clone bundles when |
209 new content is available. |
209 enough new content is available. |
210 |
210 |
211 Mercurial will take care of the process asynchronously. The defined list of |
211 Mercurial will take care of the process asynchronously. The defined list of |
212 bundle-type will be generated, uploaded, and advertised. Older bundles will get |
212 bundle-type will be generated, uploaded, and advertised. Older bundles will get |
213 decommissioned as newer ones replace them. |
213 decommissioned as newer ones replace them. |
214 |
214 |
220 |
220 |
221 [clone-bundles] |
221 [clone-bundles] |
222 auto-generate.formats= zstd-v2, gzip-v2 |
222 auto-generate.formats= zstd-v2, gzip-v2 |
223 |
223 |
224 See `hg help bundlespec` for details about available options. |
224 See `hg help bundlespec` for details about available options. |
|
225 |
|
226 Bundles are not generated on each push. By default new bundles are generated |
|
227 when 5% of the repository content is not contained in the cached bundles. This |
|
228 option can be controled by the `clone-bundles.trigger.below-bundled-ratio` |
|
229 option (default to 0.95). |
225 |
230 |
226 Bundles Upload and Serving: |
231 Bundles Upload and Serving: |
227 ........................... |
232 ........................... |
228 |
233 |
229 The generated bundles need to be made available to users through a "public" URL. |
234 The generated bundles need to be made available to users through a "public" URL. |
309 |
314 |
310 cmdtable = {} |
315 cmdtable = {} |
311 command = registrar.command(cmdtable) |
316 command = registrar.command(cmdtable) |
312 |
317 |
313 configitem(b'clone-bundles', b'auto-generate.formats', default=list) |
318 configitem(b'clone-bundles', b'auto-generate.formats', default=list) |
314 |
319 configitem(b'clone-bundles', b'trigger.below-bundled-ratio', default=0.95) |
315 |
320 |
316 configitem(b'clone-bundles', b'upload-command', default=None) |
321 configitem(b'clone-bundles', b'upload-command', default=None) |
317 |
322 |
318 configitem(b'clone-bundles', b'delete-command', default=None) |
323 configitem(b'clone-bundles', b'delete-command', default=None) |
319 |
324 |
765 uploaded.""" |
770 uploaded.""" |
766 create_bundles = [] |
771 create_bundles = [] |
767 delete_bundles = [] |
772 delete_bundles = [] |
768 repo = repo.filtered(b"immutable") |
773 repo = repo.filtered(b"immutable") |
769 targets = repo.ui.configlist(b'clone-bundles', b'auto-generate.formats') |
774 targets = repo.ui.configlist(b'clone-bundles', b'auto-generate.formats') |
|
775 ratio = float( |
|
776 repo.ui.config(b'clone-bundles', b'trigger.below-bundled-ratio') |
|
777 ) |
770 revs = len(repo.changelog) |
778 revs = len(repo.changelog) |
771 generic_data = { |
779 generic_data = { |
772 'revs': revs, |
780 'revs': revs, |
773 'head_revs': repo.changelog.headrevs(), |
781 'head_revs': repo.changelog.headrevs(), |
774 'tip_rev': repo.changelog.tiprev(), |
782 'tip_rev': repo.changelog.tiprev(), |
775 'tip_node': node.hex(repo.changelog.tip()), |
783 'tip_node': node.hex(repo.changelog.tip()), |
776 'op_id': op_id, |
784 'op_id': op_id, |
777 } |
785 } |
778 for t in targets: |
786 for t in targets: |
779 data = generic_data.copy() |
787 if new_bundle_needed(repo, bundles, ratio, t, revs): |
780 data['bundle_type'] = t |
788 data = generic_data.copy() |
781 b = RequestedBundle(**data) |
789 data['bundle_type'] = t |
782 create_bundles.append(b) |
790 b = RequestedBundle(**data) |
|
791 create_bundles.append(b) |
783 delete_bundles.extend(find_outdated_bundles(repo, bundles)) |
792 delete_bundles.extend(find_outdated_bundles(repo, bundles)) |
784 return create_bundles, delete_bundles |
793 return create_bundles, delete_bundles |
|
794 |
|
795 |
|
796 def new_bundle_needed(repo, bundles, ratio, bundle_type, revs): |
|
797 """consider the current cached content and trigger new bundles if needed""" |
|
798 threshold = revs * ratio |
|
799 for b in bundles: |
|
800 if not b.valid_for(repo) or b.bundle_type != bundle_type: |
|
801 continue |
|
802 if b.revs > threshold: |
|
803 return False |
|
804 return True |
785 |
805 |
786 |
806 |
787 def start_one_bundle(repo, bundle): |
807 def start_one_bundle(repo, bundle): |
788 """start the generation of a single bundle file |
808 """start the generation of a single bundle file |
789 |
809 |