map: Support --json option

Sponsored-by: Dartmouth College's OpenNeuro project
This commit is contained in:
Joey Hess 2025-05-28 14:17:28 -04:00
parent 4a98d12b7d
commit 52a8b5b117
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
5 changed files with 113 additions and 17 deletions

View file

@ -6,6 +6,7 @@ git-annex (10.20250521) UNRELEASED; urgency=medium
configured but fails, prevent initialization. This allows the user to configured but fails, prevent initialization. This allows the user to
fix their configuration and avoid crippled filesystem detection fix their configuration and avoid crippled filesystem detection
entering an adjusted branch. entering an adjusted branch.
* map: Support --json option.
-- Joey Hess <id@joeyh.name> Thu, 22 May 2025 12:43:38 -0400 -- Joey Hess <id@joeyh.name> Thu, 22 May 2025 12:43:38 -0400

View file

@ -9,8 +9,6 @@
module Command.Map where module Command.Map where
import qualified Data.Map as M
import Command import Command
import qualified Git import qualified Git
import qualified Git.Url import qualified Git.Url
@ -25,12 +23,17 @@ import Logs.Trust
import Types.TrustLevel import Types.TrustLevel
import qualified Remote.Helper.Ssh as Ssh import qualified Remote.Helper.Ssh as Ssh
import qualified Utility.Dot as Dot import qualified Utility.Dot as Dot
import qualified Messages.JSON as JSON
import Messages.JSON ((.=))
import Utility.Aeson (packString)
import qualified Data.Map as M
-- a repo and its remotes -- a repo and its remotes
type RepoRemotes = (Git.Repo, [Git.Repo]) type RepoRemotes = (Git.Repo, [Git.Repo])
cmd :: Command cmd :: Command
cmd = dontCheck repoExists $ cmd = dontCheck repoExists $ withAnnexOptions [jsonOptions] $
command "map" SectionQuery command "map" SectionQuery
"generate map of repositories" "generate map of repositories"
paramNothing (withParams seek) paramNothing (withParams seek)
@ -45,19 +48,23 @@ start = startingNoMessage (ActionItemOther Nothing) $ do
umap <- uuidDescMap umap <- uuidDescMap
trustmap <- trustMapLoad trustmap <- trustMapLoad
file <- (</>) ifM (outputJSONMap rs trustmap umap)
<$> fromRepo gitAnnexDir ( next $ return True
<*> pure (literalOsPath "map.dot") , do
file <- (</>)
<$> fromRepo gitAnnexDir
<*> pure (literalOsPath "map.dot")
liftIO $ writeFile (fromOsPath file) (drawMap rs trustmap umap) liftIO $ writeFile (fromOsPath file) (drawMap rs trustmap umap)
next $ next $
ifM (Annex.getRead Annex.fast) ifM (Annex.getRead Annex.fast)
( runViewer file [] ( runViewer file []
, runViewer file , runViewer file
[ ("xdot", [File (fromOsPath file)]) [ ("xdot", [File (fromOsPath file)])
, ("dot", [Param "-Tx11", File (fromOsPath file)]) , ("dot", [Param "-Tx11", File (fromOsPath file)])
] ]
) )
)
runViewer :: OsPath -> [(String, [CommandParam])] -> Annex Bool runViewer :: OsPath -> [(String, [CommandParam])] -> Annex Bool
runViewer file [] = do runViewer file [] = do
@ -198,7 +205,8 @@ same a b
{- reads the config of a remote, with progress display -} {- reads the config of a remote, with progress display -}
scan :: Git.Repo -> Annex Git.Repo scan :: Git.Repo -> Annex Git.Repo
scan r = do scan r = do
showStartMessage (StartMessage "map" (ActionItemOther (Just $ UnquotedString $ Git.repoDescribe r)) (SeekInput [])) unlessM jsonOutputEnabled $
showStartMessage (StartMessage "map" (ActionItemOther (Just $ UnquotedString $ Git.repoDescribe r)) (SeekInput []))
v <- tryScan r v <- tryScan r
case v of case v of
Just r' -> do Just r' -> do
@ -269,7 +277,7 @@ tryScan r
configlist configlist
ok -> return ok ok -> return ok
sshnote = do sshnote = unlessM jsonOutputEnabled $ do
showAction "sshing" showAction "sshing"
showOutput showOutput
@ -287,3 +295,33 @@ safely a = do
case result of case result of
Left _ -> return Nothing Left _ -> return Nothing
Right r' -> return $ Just r' Right r' -> return $ Just r'
outputJSONMap :: [RepoRemotes] -> TrustMap -> UUIDDescMap -> Annex Bool
outputJSONMap rs trustmap umap =
showFullJSON $ JSON.AesonObject $ case mapo of
JSON.Object obj -> obj
_ -> error "internal"
where
mapo = JSON.object
[ "nodes" .= map mknode (filterdead fst rs)
]
mknode (r, remotes) = JSON.object
[ "name" .= packString (repoName umap r)
, "uuid" .= mkuuid (getUncachedUUID r)
, "url" .= packString (Git.repoLocation r)
, "remotes" .= map mkremote (filterdead id remotes)
]
mkremote r = JSON.object
[ "name" .= packString (repoName umap r)
, "uuid" .= mkuuid (getUncachedUUID r)
, "url" .= packString (Git.repoLocation r)
]
mkuuid NoUUID = Nothing
mkuuid u = Just $ packString $ fromUUID u
filterdead f = filter
(\i -> M.lookup (getUncachedUUID (f i)) trustmap /= Just DeadTrusted)

View file

@ -39,6 +39,10 @@ on that host.
Don't display the generated Graphviz file, but save it for later use. Don't display the generated Graphviz file, but save it for later use.
* `--json`
Output the map as a JSON object.
* Also the [[git-annex-common-options]](1) can be used. * Also the [[git-annex-common-options]](1) can be used.
# SEE ALSO # SEE ALSO

View file

@ -6,3 +6,5 @@ Please let me know on how feasible that would be, and any other thoughts you hav
[[!meta author=yoh]] [[!meta author=yoh]]
[[!tag projects/openneuro]] [[!tag projects/openneuro]]
> [[done]] --[[Joey]]

View file

@ -0,0 +1,51 @@
[[!comment format=mdwn
username="joey"
subject="""comment 2"""
date="2025-05-28T18:11:34Z"
content="""
I went ahead and implemented `git-annx map --json`.
Example output, after being passed through `jq` to pretty-print it:
{
"nodes": [
{
"name": "joey@darkstar:~/tmp/mapbench/a",
"remotes": [
{
"name": "joey@darkstar:~/tmp/mapbench/b",
"url": "/home/joey/tmp/mapbench/b",
"uuid": "645d92d8-6461-43c1-b23c-6dd04dc3a015"
}
],
"url": "/home/joey/tmp/mapbench/a",
"uuid": "3f34e4c2-dd19-433a-ab04-9fd4be959325"
},
{
"name": "joey@darkstar:~/tmp/mapbench/b",
"remotes": [
{
"name": "joey@darkstar:~/tmp/mapbench/a",
"url": "/home/joey/tmp/mapbench/a",
"uuid": "3f34e4c2-dd19-433a-ab04-9fd4be959325"
}
],
"url": "/home/joey/tmp/mapbench/b",
"uuid": "645d92d8-6461-43c1-b23c-6dd04dc3a015"
},
{
"name": "unknown",
"remotes": [
{
"name": "joey@darkstar:~/tmp/mapbench/b",
"url": "/home/joey/tmp/mapbench/b",
"uuid": "645d92d8-6461-43c1-b23c-6dd04dc3a015"
}
],
"url": ".",
"uuid": null
}
],
"error-messages": []
}
"""]]