tahoe: Support tahoe-lafs command versions newer than 1.16
authorJoey Hess <joeyh@joeyh.name>
Fri, 22 Aug 2025 16:35:53 +0000 (12:35 -0400)
committerJoey Hess <joeyh@joeyh.name>
Fri, 22 Aug 2025 16:35:53 +0000 (12:35 -0400)
tahoe start was deprecated and removed in 2020.

This feels like a very janky way to run a daemon, but it does work.

Sponsored-by: k0ld
CHANGELOG
Remote/Tahoe.hs
doc/bugs/tahoe_special_remote_needs_updating.mdwn

index 76387efc6fb56c2c67837cb16b15eccddef1c87f..9a478550fe89660aea5b0998550b59bee8b9e814 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -26,6 +26,7 @@ git-annex (10.20250722) UNRELEASED; urgency=medium
     for exporttree=yes/importtree=yes remotes.
   * Don't allow the type of encryption of an existing special remote to be
     changed. Fixes reversion introduced in version 7.20191230.
+  * tahoe: Support tahoe-lafs command versions newer than 1.16.
   * Removed support for git versions older than 2.22.
   * Bump aws build dependency to 0.24.1.
   * stack.yaml: Update to lts-24.2.
index 9495a3c082d9305e3e8cb8906e75fc722a42f11b..76b17caa5bd72e0d76b79c29ad6dee9bc04f0d8a 100644 (file)
@@ -13,7 +13,7 @@
  -
  - Tahoe has its own encryption, so git-annex's encryption is not used.
  -
- - Copyright 2014-2020 Joey Hess <id@joeyh.name>
+ - Copyright 2014-2025 Joey Hess <id@joeyh.name>
  -
  - Licensed under the GNU AGPL version 3 or higher.
  -}
@@ -45,6 +45,9 @@ import Utility.UserInfo
 import Utility.Metered
 import Utility.Env
 import Utility.ThreadScheduler
+import Utility.Process.Transcript
+
+import Control.Concurrent
 
 {- The TMVar is left empty until tahoe has been verified to be running. -}
 data TahoeHandle = TahoeHandle TahoeConfigDir (TMVar ())
@@ -233,8 +236,42 @@ convergenceFile :: TahoeConfigDir -> OsPath
 convergenceFile configdir = 
        configdir </> literalOsPath "private" </> literalOsPath "convergence"
 
+{- tahoe run stays in the foreground, but behaves as a daemon, servicing
+ - requests. Attempting to start a second tahoe run process will fail. So,
+ - in order to support multiple git-annex processes, it is run in the
+ - background, and left running on exit.
+ -
+ - It can take a while for tahoe to begin accepting connections.
+ - This function waits for it to get ready.
+ -}
 startTahoeDaemon :: TahoeConfigDir -> IO ()
-startTahoeDaemon configdir = void $ boolTahoe configdir "start" []
+startTahoeDaemon configdir = withNullHandle $ \nullh -> do
+       let ps = tahoeParams configdir "run" [Param "--allow-stdin-close"]
+       let p = (proc "tahoe" $ toCommand ps)
+               { std_in = UseHandle nullh
+               , std_out = UseHandle nullh
+               , std_err = UseHandle nullh
+               }
+       void $ forkIO $ void $ createProcess p
+       waitready (5 :: Int)
+       hClose nullh
+  where
+       waitready n
+               | n <= 0 = giveup "The tahoe run process is not responding to requests. Waited 5 seconds for it to start."
+               | otherwise = do
+                       -- Need something that will always succeed
+                       -- once the server has started and is accepting
+                       -- requests, and this seems to do the trick.
+                       let ps = tahoeParams configdir "check"
+                               [ Param "--raw", Param "URI:LIT:"]
+                       (_, ok) <- processTranscript "tahoe" 
+                               (toCommand ps)
+                               Nothing
+                       if ok
+                               then return ()
+                               else do
+                                       threadDelaySeconds (Seconds 1)
+                                       waitready (pred n)
 
 {- Ensures that tahoe has been started, before running an action
  - that uses it. -}
index e7b1aaf831f442373fca1217dda87181ca0245b8..d9ff806b07ea877161716b070f3d8b48a286fb2e 100644 (file)
@@ -13,3 +13,4 @@ The tahoe man page says:
           COMMANDS
               run    Run a node without daemonizing.  This is the only command for running nodes.
 
+> [[done]] --[[Joey]]