clone-bundles: introduce a command to refresh bundle
authorPierre-Yves David <pierre-yves.david@octobus.net>
Mon, 13 Mar 2023 19:16:19 +0100
changeset 50408 23db5f15cc0c
parent 50407 65fb4cedd5ea
child 50409 a53b8ddf8f3f
clone-bundles: introduce a command to refresh bundle This command allows for a different mode than the one attached to the transation. It might fit some hosting setup better.
hgext/clonebundles.py
tests/test-clonebundles-autogen.t
tests/test-help.t
--- a/hgext/clonebundles.py	Mon Mar 13 04:18:45 2023 +0100
+++ b/hgext/clonebundles.py	Mon Mar 13 19:16:19 2023 +0100
@@ -232,7 +232,8 @@
     trigger.below-bundled-ratio=0.95
     trigger.revs=1000
 
-This logic can be automatically triggered on each repository changes if
+This logic can be manually triggered using the `admin::clone-bundles-refresh`
+command, or automatically on each repository change if
 `clone-bundles.auto-generate.on-change` is set to `yes`.
 
     [clone-bundles]
@@ -939,3 +940,40 @@
     repo._wlockfreeprefix.add(AUTO_GEN_FILE)
     repo._wlockfreeprefix.add(bundlecaches.CB_MANIFEST_FILE)
     repo.__class__ = autobundlesrepo
+
+
+@command(b'admin::clone-bundles-refresh', [], b'')
+def cmd_admin_clone_bundles_refresh(ui, repo: localrepo.localrepository):
+    """generate clone bundles according to the configuration
+
+    This runs the logic for automatic generation, removing outdated bundles and
+    generating new ones if necessary. See :hg:`help -e clone-bundles` for
+    details about how to configure this feature.
+    """
+    debug = repo.ui.configbool(b'devel', b'debug.clonebundles')
+    bundles = read_auto_gen(repo)
+    op_id = b"%d_acbr" % os.getpid()
+    create, delete = auto_bundle_needed_actions(repo, bundles, op_id)
+
+    # we clean up outdated bundle before generating new one to keep the last
+    # two version of the bundle around for a while and avoid having to deal
+    # client that just got served a manifest.
+    for o in delete:
+        delete_bundle(repo, o)
+    update_bundle_list(repo, del_bundles=delete)
+
+    if create:
+        fpath = repo.vfs.makedirs(b'tmp-bundles')
+    for requested_bundle in create:
+        if debug:
+            msg = b'clone-bundles: starting bundle generation: %s\n'
+            repo.ui.write(msg % requested_bundle.bundle_type)
+        fname = requested_bundle.suggested_filename
+        fpath = repo.vfs.join(b'tmp-bundles', fname)
+        generating_bundle = requested_bundle.generating(fpath)
+        update_bundle_list(repo, new_bundles=[generating_bundle])
+        requested_bundle.generate_bundle(repo, fpath)
+        result = upload_bundle(repo, generating_bundle)
+        update_bundle_list(repo, new_bundles=[result])
+        update_ondisk_manifest(repo)
+        cleanup_tmp_bundle(repo, generating_bundle)
--- a/tests/test-clonebundles-autogen.t	Mon Mar 13 04:18:45 2023 +0100
+++ b/tests/test-clonebundles-autogen.t	Mon Mar 13 19:16:19 2023 +0100
@@ -163,3 +163,96 @@
   full-v2-6_revs-b1010e95ea00_tip-*_txn.hg (glob)
   full-v2-8_revs-8353e8af1306_tip-*_txn.hg (glob)
   $ ls -1 ../server/.hg/tmp-bundles
+
+Test generation through the dedicated command
+=============================================
+
+  $ cat >> ../server/.hg/hgrc << EOF
+  > [clone-bundles]
+  > auto-generate.on-change = no
+  > EOF
+
+Check the command can generate content when needed
+--------------------------------------------------
+
+Do a push that makes the condition fulfilled,
+Yet it should not automatically generate a bundle with
+"auto-generate.on-change" not set.
+
+  $ touch quoi
+  $ hg -q commit -A -m 'add quoi'
+
+  $ pre_push_manifest=`cat ../server/.hg/clonebundles.manifest|f --sha256 | sed 's/.*=//' | cat`
+  $ pre_push_upload=`ls -1 ../final-upload|f --sha256 | sed 's/.*=//' | cat`
+  $ ls -1 ../server/.hg/tmp-bundles
+
+  $ hg push
+  pushing to $TESTTMP/server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+
+  $ post_push_manifest=`cat ../server/.hg/clonebundles.manifest|f --sha256 | sed 's/.*=//' | cat`
+  $ post_push_upload=`ls -1 ../final-upload|f --sha256 | sed 's/.*=//' | cat`
+  $ ls -1 ../server/.hg/tmp-bundles
+  $ test "$pre_push_manifest" = "$post_push_manifest"
+  $ test "$pre_push_upload" = "$post_push_upload"
+
+Running the command should detect the stale bundles, and do the full automatic
+generation logic.
+
+  $ hg -R ../server/ admin::clone-bundles-refresh
+  clone-bundles: deleting bundle full-v2-6_revs-b1010e95ea00_tip-*_txn.hg (glob)
+  clone-bundles: starting bundle generation: v2
+  10 changesets found
+  $ cat ../server/.hg/clonebundles.manifest
+  file:/*/$TESTTMP/final-upload/full-v2-10_revs-3b6f57f17d70_tip-*_acbr.hg BUNDLESPEC=v2 REQUIRESNI=true (glob)
+  $ ls -1 ../final-upload
+  full-v2-10_revs-3b6f57f17d70_tip-*_acbr.hg (glob)
+  full-v2-8_revs-8353e8af1306_tip-*_txn.hg (glob)
+  $ ls -1 ../server/.hg/tmp-bundles
+
+Check the command cleans up older bundles when possible
+-------------------------------------------------------
+
+  $ hg -R ../server/ admin::clone-bundles-refresh
+  clone-bundles: deleting bundle full-v2-8_revs-8353e8af1306_tip-*_txn.hg (glob)
+  $ cat ../server/.hg/clonebundles.manifest
+  file:/*/$TESTTMP/final-upload/full-v2-10_revs-3b6f57f17d70_tip-*_acbr.hg BUNDLESPEC=v2 REQUIRESNI=true (glob)
+  $ ls -1 ../final-upload
+  full-v2-10_revs-3b6f57f17d70_tip-*_acbr.hg (glob)
+  $ ls -1 ../server/.hg/tmp-bundles
+
+Nothing is generated when the bundles are sufficiently up to date
+-----------------------------------------------------------------
+
+  $ touch feur
+  $ hg -q commit -A -m 'add feur'
+
+  $ pre_push_manifest=`cat ../server/.hg/clonebundles.manifest|f --sha256 | sed 's/.*=//' | cat`
+  $ pre_push_upload=`ls -1 ../final-upload|f --sha256 | sed 's/.*=//' | cat`
+  $ ls -1 ../server/.hg/tmp-bundles
+
+  $ hg push
+  pushing to $TESTTMP/server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+
+  $ post_push_manifest=`cat ../server/.hg/clonebundles.manifest|f --sha256 | sed 's/.*=//' | cat`
+  $ post_push_upload=`ls -1 ../final-upload|f --sha256 | sed 's/.*=//' | cat`
+  $ ls -1 ../server/.hg/tmp-bundles
+  $ test "$pre_push_manifest" = "$post_push_manifest"
+  $ test "$pre_push_upload" = "$post_push_upload"
+
+  $ hg -R ../server/ admin::clone-bundles-refresh
+
+  $ post_refresh_manifest=`cat ../server/.hg/clonebundles.manifest|f --sha256 | sed 's/.*=//' | cat`
+  $ post_refresh_upload=`ls -1 ../final-upload|f --sha256 | sed 's/.*=//' | cat`
+  $ ls -1 ../server/.hg/tmp-bundles
+  $ test "$pre_push_manifest" = "$post_refresh_manifest"
+  $ test "$pre_push_upload" = "$post_refresh_upload"
--- a/tests/test-help.t	Mon Mar 13 04:18:45 2023 +0100
+++ b/tests/test-help.t	Mon Mar 13 19:16:19 2023 +0100
@@ -1782,7 +1782,9 @@
   
   Extension Commands:
   
-   qclone clone main and patch repository at same time
+   admin::clone-bundles-refresh generate clone bundles according to the
+                                configuration
+   qclone                       clone main and patch repository at same time
 
 Test unfound topic