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
fix their configuration and avoid crippled filesystem detection
entering an adjusted branch.
* map: Support --json option.
-- Joey Hess <id@joeyh.name> Thu, 22 May 2025 12:43:38 -0400

View file

@ -9,8 +9,6 @@
module Command.Map where
import qualified Data.Map as M
import Command
import qualified Git
import qualified Git.Url
@ -25,12 +23,17 @@ import Logs.Trust
import Types.TrustLevel
import qualified Remote.Helper.Ssh as Ssh
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
type RepoRemotes = (Git.Repo, [Git.Repo])
cmd :: Command
cmd = dontCheck repoExists $
cmd = dontCheck repoExists $ withAnnexOptions [jsonOptions] $
command "map" SectionQuery
"generate map of repositories"
paramNothing (withParams seek)
@ -45,19 +48,23 @@ start = startingNoMessage (ActionItemOther Nothing) $ do
umap <- uuidDescMap
trustmap <- trustMapLoad
file <- (</>)
<$> fromRepo gitAnnexDir
<*> pure (literalOsPath "map.dot")
ifM (outputJSONMap rs trustmap umap)
( next $ return True
, do
file <- (</>)
<$> fromRepo gitAnnexDir
<*> pure (literalOsPath "map.dot")
liftIO $ writeFile (fromOsPath file) (drawMap rs trustmap umap)
next $
ifM (Annex.getRead Annex.fast)
( runViewer file []
, runViewer file
[ ("xdot", [File (fromOsPath file)])
, ("dot", [Param "-Tx11", File (fromOsPath file)])
]
)
liftIO $ writeFile (fromOsPath file) (drawMap rs trustmap umap)
next $
ifM (Annex.getRead Annex.fast)
( runViewer file []
, runViewer file
[ ("xdot", [File (fromOsPath file)])
, ("dot", [Param "-Tx11", File (fromOsPath file)])
]
)
)
runViewer :: OsPath -> [(String, [CommandParam])] -> Annex Bool
runViewer file [] = do
@ -198,7 +205,8 @@ same a b
{- reads the config of a remote, with progress display -}
scan :: Git.Repo -> Annex Git.Repo
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
case v of
Just r' -> do
@ -269,7 +277,7 @@ tryScan r
configlist
ok -> return ok
sshnote = do
sshnote = unlessM jsonOutputEnabled $ do
showAction "sshing"
showOutput
@ -287,3 +295,33 @@ safely a = do
case result of
Left _ -> return Nothing
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.
* `--json`
Output the map as a JSON object.
* Also the [[git-annex-common-options]](1) can be used.
# 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]]
[[!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": []
}
"""]]