diff --git a/CHANGELOG b/CHANGELOG
index d956868768..89df0811c6 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,9 @@
git-annex (10.20240532) UNRELEASED; urgency=medium
- * Added updateproxy command and remote.name.annex-proxy configuration.
+ * Added git-annex updateproxy command and remote.name.annex-proxy
+ configuration.
+ * Added git-annex cluster command and remote.name.annex-cluster-node
+ and annex.cluster.name configuration.
* Fix a bug where interrupting git-annex while it is updating the
git-annex branch for an export could later lead to git fsck
complaining about missing tree objects.
diff --git a/Types/Cluster.hs b/Types/Cluster.hs
index 0ce3e0db0b..08a349f3ba 100644
--- a/Types/Cluster.hs
+++ b/Types/Cluster.hs
@@ -34,8 +34,8 @@ newtype ClusterUUID = ClusterUUID UUID
-- Smart constructor for a ClusterUUID.
--
--- The input UUID can be a regular UUID (eg V4). It is converted to a valid
--- cluster uuid.
+-- The input UUID can be any regular UUID (eg V4). It is converted to a valid
+-- cluster UUID.
mkClusterUUID :: UUID -> Maybe ClusterUUID
mkClusterUUID (UUID b)
| B.length b > 14 = Just $ ClusterUUID $ UUID $
diff --git a/Types/GitConfig.hs b/Types/GitConfig.hs
index b72dc29c5c..016e51a68a 100644
--- a/Types/GitConfig.hs
+++ b/Types/GitConfig.hs
@@ -45,6 +45,7 @@ import Types.RefSpec
import Types.RepoVersion
import Types.StallDetection
import Types.View
+import Types.Cluster
import Config.DynamicConfig
import Utility.HumanTime
import Utility.Gpg (GpgCmd, mkGpgCmd)
@@ -155,6 +156,7 @@ data GitConfig = GitConfig
, annexPrivateRepos :: S.Set UUID
, annexAdviceNoSshCaching :: Bool
, annexViewUnsetDirectory :: ViewUnset
+ , annexClusters :: M.Map String ClusterUUID
}
extractGitConfig :: ConfigSource -> Git.Repo -> GitConfig
@@ -283,6 +285,12 @@ extractGitConfig configsource r = GitConfig
, annexAdviceNoSshCaching = getbool (annexConfig "advicenosshcaching") True
, annexViewUnsetDirectory = ViewUnset $ fromMaybe "_" $
getmaybe (annexConfig "viewunsetdirectory")
+ , annexClusters =
+ M.mapMaybe (mkClusterUUID . toUUID) $
+ M.mapKeys (drop (B.length clusterprefix) . fromConfigKey) $
+ M.filterWithKey
+ (\(ConfigKey k) _ -> clusterprefix `B.isPrefixOf` k)
+ (config r)
}
where
getbool k d = fromMaybe d $ getmaybebool k
@@ -307,6 +315,8 @@ extractGitConfig configsource r = GitConfig
hereuuid = maybe NoUUID toUUID $ getmaybe (annexConfig "uuid")
+ clusterprefix = annexConfigPrefix <> "cluster."
+
{- Merge a GitConfig that comes from git-config with one containing
- repository-global defaults. -}
mergeGitConfig :: GitConfig -> GitConfig -> GitConfig
@@ -377,6 +387,7 @@ data RemoteGitConfig = RemoteGitConfig
, remoteAnnexMaxGitBundles :: Int
, remoteAnnexAllowEncryptedGitRepo :: Bool
, remoteAnnexProxy :: Bool
+ , remoteAnnexClusterNode :: Maybe [String]
, remoteUrl :: Maybe String
{- These settings are specific to particular types of remotes
@@ -462,6 +473,7 @@ extractRemoteGitConfig r remotename = do
, remoteAnnexAllowEncryptedGitRepo =
getbool AllowEncryptedGitRepoField False
, remoteAnnexProxy = getbool ProxyField False
+ , remoteAnnexClusterNode = words <$> getmaybe ClusterNodeField
, remoteUrl =
case Git.Config.getMaybe (remoteConfig remotename (remoteGitConfigKey UrlField)) r of
Just (ConfigValue b)
@@ -539,6 +551,7 @@ data RemoteGitConfigField
| MaxGitBundlesField
| AllowEncryptedGitRepoField
| ProxyField
+ | ClusterNodeField
| UrlField
| ShellField
| SshOptionsField
@@ -603,6 +616,7 @@ remoteGitConfigField = \case
AllowEncryptedGitRepoField -> inherited "allow-encrypted-gitrepo"
-- Allow proxy chains.
ProxyField -> inherited "proxy"
+ ClusterNodeField -> uninherited "cluster-node"
UrlField -> inherited "url"
ShellField -> inherited "shell"
SshOptionsField -> inherited "ssh-options"
@@ -654,9 +668,12 @@ dummyRemoteGitConfig = atomically $
type UnqualifiedConfigKey = B.ByteString
+annexConfigPrefix :: B.ByteString
+annexConfigPrefix = "annex."
+
{- A global annex setting in git config. -}
annexConfig :: UnqualifiedConfigKey -> ConfigKey
-annexConfig key = ConfigKey ("annex." <> key)
+annexConfig key = ConfigKey (annexConfigPrefix <> key)
class RemoteNameable r where
getRemoteName :: r -> RemoteName
diff --git a/doc/git-annex-preferred-content.mdwn b/doc/git-annex-preferred-content.mdwn
index 890c519596..466215792a 100644
--- a/doc/git-annex-preferred-content.mdwn
+++ b/doc/git-annex-preferred-content.mdwn
@@ -8,7 +8,7 @@ Each repository has a preferred content setting, which specifies content
that the repository wants to have present. These settings can be configured
using `git annex vicfg` or `git annex wanted`.
They are used by the `--auto` option, by `git annex sync --content`,
-and by the git-annex assistant.
+by clusters, and by the git-annex assistant.
While preferred content expresses a preference, it can be overridden
by simply using `git annex drop`. On the other hand, required content
diff --git a/doc/git-annex-updateproxy.mdwn b/doc/git-annex-updateproxy.mdwn
index 20cbeef278..9ce216e52b 100644
--- a/doc/git-annex-updateproxy.mdwn
+++ b/doc/git-annex-updateproxy.mdwn
@@ -22,7 +22,9 @@ git-annex branch. That tells other repositories about the proxy
configuration.
Suppose, for example, that remote "work" has had this command run in
-it. Then git-annex will know about an additional remote, "work-foo".
+it. Then after pulling from "work", git-annex will know about an
+additional remote, "work-foo". That remote will be accessed using "work" as
+a proxy. (This only works for remotes accessed over ssh.)
# OPTIONS
@@ -31,6 +33,7 @@ it. Then git-annex will know about an additional remote, "work-foo".
# SEE ALSO
[[git-annex]](1)
+[[git-annex-cluster]](1)
# AUTHOR
diff --git a/doc/git-annex.mdwn b/doc/git-annex.mdwn
index 3a7a6bd39f..a6a303610c 100644
--- a/doc/git-annex.mdwn
+++ b/doc/git-annex.mdwn
@@ -1377,6 +1377,14 @@ repository, using [[git-annex-config]]. See its man page for a list.)
set in global git configuration.
For details, see .
+* `annex.cluster.`
+
+ [[git-annex-cluster]] sets this to the UUID of a cluster, to
+ enable the local repository to act as a proxy to the cluster.
+
+ Note that cluster UUIDs are not the same as repository UUIDs,
+ and a repository UUID cannot be used here.
+
# CONFIGURATION OF REMOTES
Remotes are configured using these settings in `.git/config`.
@@ -1649,7 +1657,18 @@ Remotes are configured using these settings in `.git/config`.
* `remote..annex-proxy`
Set to "true" to make the local repository able to act as a proxy to this
- remote. After configuring this, run [[git-annex-updateproxy](1) to store
+ remote.
+
+ After configuring this, run [[git-annex-updateproxy](1) to store
+ the new configuration in the git-annex branch.
+
+* `remote..annex-cluster-node`
+
+ Set to the name of a cluster to make this remote be part of
+ the cluster. Names of multiple clusters can be separated by
+ whitespace to make a remote be part of more than one cluster.
+
+ After configuring this, run [[git-annex-updatecluster](1) to store
the new configuration in the git-annex branch.
* `remote..annex-private`