diff options
author | joe <joe@jerkface.net> | 2014-05-05 21:40:16 -0400 |
---|---|---|
committer | joe <joe@jerkface.net> | 2014-05-05 21:40:16 -0400 |
commit | 9deb2a81dcfc3c4489824d5a753cbe03fe82c492 (patch) | |
tree | 1768763b39a8005f7c175bb9952949ac2eb54c7f /kiki.hs | |
parent | 67904f836d39cc844f85c2570d5a634d59a8f020 (diff) |
better usage message for "merge" command
Diffstat (limited to 'kiki.hs')
-rw-r--r-- | kiki.hs | 200 |
1 files changed, 116 insertions, 84 deletions
@@ -872,97 +872,129 @@ kiki "show" args = do | |||
872 | forM_ report $ \(fname,act) -> do | 872 | forM_ report $ \(fname,act) -> do |
873 | putStrLn $ fname ++ ": " ++ reportString act | 873 | putStrLn $ fname ++ ": " ++ reportString act |
874 | 874 | ||
875 | kiki "merge" [] = do | ||
876 | putStr . unlines $ | ||
877 | [ "kiki merge ( --home[=HOMEDIR]" | ||
878 | , " | --type=(keyring|pem|wallet|hosts)" | ||
879 | , " | --access=[auto|secret|public]" | ||
880 | , " | --flow=(fill|spill|sync)[,(subkeys|match=KEYSPEC)]" | ||
881 | , " | --create=CMD" | ||
882 | , " | --autosign[=no]" | ||
883 | , " | --" | ||
884 | , " | FILE ) ..."] | ||
885 | kiki "merge" args | "--help" `elem` args = do | ||
886 | kiki "merge" [] | ||
887 | -- TODO: more help | ||
875 | kiki "merge" args = do | 888 | kiki "merge" args = do |
876 | let op = snd $ foldl' buildOp (flow,noop) args | ||
877 | noop = KeyRingOperation | ||
878 | { opFiles = Map.empty | ||
879 | , opTransforms = [] | ||
880 | , opHome = Nothing | ||
881 | , opPassphrases = [] | ||
882 | } | ||
883 | flow = StreamInfo | ||
884 | { access = AutoAccess | ||
885 | , typ = KeyRingFile | ||
886 | , spill = KF_None | ||
887 | , fill = KF_None | ||
888 | , initializer = Nothing | ||
889 | , transforms = [] | ||
890 | } | ||
891 | updateFlow fil spil mtch flow = spill' $ fill' $ flow | ||
892 | where | ||
893 | fill' flow = flow { fill = if fil then val else KF_None } | ||
894 | spill' flow = flow { spill = if spil then val else KF_None } | ||
895 | val = either (\subkeys -> if subkeys then KF_Subkeys else KF_All) | ||
896 | KF_Match | ||
897 | mtch | ||
898 | parseFlow spec = | ||
899 | if null bads | ||
900 | then Just ( ( "spill" `elem` goods | ||
901 | || "sync" `elem` goods | ||
902 | , "fill" `elem` goods | ||
903 | || "sync" `elem` goods ) | ||
904 | , maybe (Left $ "subkeys" `elem` goods) | ||
905 | Right | ||
906 | match ) | ||
907 | else Nothing | ||
908 | where | ||
909 | ws = case groupBy (\_ c->c/=',') spec of | ||
910 | w:xs -> w:map (drop 1) xs | ||
911 | [] -> [] | ||
912 | (goods,bads) = partition acceptable ws | ||
913 | acceptable "spill" = True | ||
914 | acceptable "fill" = True | ||
915 | acceptable "sync" = True | ||
916 | acceptable "subkeys" = True | ||
917 | acceptable s | "match=" `isPrefixOf` s = True | ||
918 | acceptable _ = False | ||
919 | match = listToMaybe $ do | ||
920 | m <- filter ("match=" `isPrefixOf`) goods | ||
921 | return $ drop 6 m | ||
922 | |||
923 | buildOp (flow,op) arg = | ||
924 | case splitArg arg of | ||
925 | Right fname -> | ||
926 | ( flow | ||
927 | , op { opFiles= Map.insert (ArgFile fname) flow (opFiles op) }) | ||
928 | Left ("autosign",Nothing) -> | ||
929 | if Map.null (opFiles op) | ||
930 | then (flow, op { opTransforms = opTransforms op ++ [Autosign] }) | ||
931 | else (flow { transforms = transforms flow ++ [Autosign] }, op) | ||
932 | Left ("noautosign",Nothing) -> | ||
933 | ( flow { transforms = filter (/=Autosign) (transforms flow) } | ||
934 | , op { opTransforms = filter (/=Autosign) (opTransforms op) } ) | ||
935 | Left ("create",Just cmd) -> | ||
936 | ( flow { initializer = if null cmd then Nothing else Just cmd } | ||
937 | , op ) | ||
938 | Left ("type",Just "keyring") -> ( flow { typ = KeyRingFile }, op ) | ||
939 | Left ("type",Just "pem" ) -> ( flow { typ = PEMFile }, op ) | ||
940 | Left ("type",Just "wallet" ) -> ( flow { typ = WalletFile }, op ) | ||
941 | Left ("type",Just "hosts" ) -> ( flow { typ = Hosts }, op ) | ||
942 | Left ("access",Just "public") -> ( flow { access = Pub }, op ) | ||
943 | Left ("access",Just "secret") -> ( flow { access = Sec }, op ) | ||
944 | Left ("access",Just "auto") -> ( flow { access = AutoAccess }, op ) | ||
945 | Left ("home",mb) -> | ||
946 | ( flow | ||
947 | , op { opFiles = Map.insert HomePub flow { access=Pub } | ||
948 | $ Map.insert HomeSec flow { access=Sec } | ||
949 | $ opFiles op | ||
950 | , opHome = opHome op `mplus` mb | ||
951 | } | ||
952 | ) | ||
953 | Left ("flow",Just flowspec) -> | ||
954 | case parseFlow flowspec of | ||
955 | Just ( (fil,spil), mtch ) -> | ||
956 | ( updateFlow fil spil mtch flow | ||
957 | , op ) | ||
958 | Nothing -> error "Valid flow words are: spill,fill,sync,subkeys or match=KEYSPEC" | ||
959 | Left (option,_) -> error $ "Unrecognized option: " ++ option | ||
960 | KikiResult rt report <- runKeyRing op | 889 | KikiResult rt report <- runKeyRing op |
961 | case rt of | 890 | case rt of |
962 | KikiSuccess rt -> return () | 891 | KikiSuccess rt -> return () |
963 | err -> putStrLn $ errorString err | 892 | err -> putStrLn $ errorString err |
964 | forM_ report $ \(fname,act) -> do | 893 | forM_ report $ \(fname,act) -> do |
965 | putStrLn $ fname ++ ": " ++ reportString act | 894 | putStrLn $ fname ++ ": " ++ reportString act |
895 | where | ||
896 | (_,(_,op)) = foldl' buildOp (True,(flow,noop)) args | ||
897 | noop = KeyRingOperation | ||
898 | { opFiles = Map.empty | ||
899 | , opTransforms = [] | ||
900 | , opHome = Nothing | ||
901 | , opPassphrases = [] | ||
902 | } | ||
903 | flow = StreamInfo | ||
904 | { access = AutoAccess | ||
905 | , typ = KeyRingFile | ||
906 | , spill = KF_None | ||
907 | , fill = KF_None | ||
908 | , initializer = Nothing | ||
909 | , transforms = [] | ||
910 | } | ||
911 | updateFlow fil spil mtch flow = spill' $ fill' $ flow | ||
912 | where | ||
913 | fill' flow = flow { fill = if fil then val else KF_None } | ||
914 | spill' flow = flow { spill = if spil then val else KF_None } | ||
915 | val = either (\subkeys -> if subkeys then KF_Subkeys else KF_All) | ||
916 | KF_Match | ||
917 | mtch | ||
918 | parseFlow spec = | ||
919 | if null bads | ||
920 | then Just ( ( "spill" `elem` goods | ||
921 | || "sync" `elem` goods | ||
922 | , "fill" `elem` goods | ||
923 | || "sync" `elem` goods ) | ||
924 | , maybe (Left $ "subkeys" `elem` goods) | ||
925 | Right | ||
926 | match ) | ||
927 | else Nothing | ||
928 | where | ||
929 | ws = case groupBy (\_ c->c/=',') spec of | ||
930 | w:xs -> w:map (drop 1) xs | ||
931 | [] -> [] | ||
932 | (goods,bads) = partition acceptable ws | ||
933 | acceptable "spill" = True | ||
934 | acceptable "fill" = True | ||
935 | acceptable "sync" = True | ||
936 | acceptable "subkeys" = True | ||
937 | acceptable s | "match=" `isPrefixOf` s = True | ||
938 | acceptable _ = False | ||
939 | match = listToMaybe $ do | ||
940 | m <- filter ("match=" `isPrefixOf`) goods | ||
941 | return $ drop 6 m | ||
942 | |||
943 | doFile :: StreamInfo -> KeyRingOperation -> FilePath -> (StreamInfo,KeyRingOperation) | ||
944 | doFile flow op fname = | ||
945 | ( flow | ||
946 | , op { opFiles= Map.insert (ArgFile fname) flow (opFiles op) }) | ||
947 | |||
948 | doAutosign :: Bool -> StreamInfo -> KeyRingOperation -> (StreamInfo,KeyRingOperation) | ||
949 | doAutosign True flow op = | ||
950 | if Map.null (opFiles op) | ||
951 | then (flow, op { opTransforms = opTransforms op ++ [Autosign] }) | ||
952 | else (flow { transforms = transforms flow ++ [Autosign] }, op) | ||
953 | doAutosign False flow op = | ||
954 | ( flow { transforms = filter (/=Autosign) (transforms flow) } | ||
955 | , op { opTransforms = filter (/=Autosign) (opTransforms op) } ) | ||
956 | |||
957 | buildOp (False,(flow,op)) fname = (False,doFile flow op fname) | ||
958 | buildOp (True,(flow,op)) arg@(splitArg->parsed) = | ||
959 | case parsed of | ||
960 | Left ("",Nothing) -> (False,(flow,op)) | ||
961 | _ -> (True,) dispatch | ||
962 | where | ||
963 | dispatch = | ||
964 | case parsed of | ||
965 | Right fname -> doFile flow op fname | ||
966 | Left ("autosign",Nothing) -> doAutosign True flow op | ||
967 | Left ("autosign",Just "y") -> doAutosign True flow op | ||
968 | Left ("autosign",Just "yes") -> doAutosign True flow op | ||
969 | Left ("autosign",Just "true") -> doAutosign True flow op | ||
970 | Left ("autosign",Just "n") -> doAutosign False flow op | ||
971 | Left ("autosign",Just "no") -> doAutosign False flow op | ||
972 | Left ("autosign",Just "false")-> doAutosign False flow op | ||
973 | Left ("create",Just cmd) -> | ||
974 | ( flow { initializer = if null cmd then Nothing else Just cmd } | ||
975 | , op ) | ||
976 | Left ("type",Just "keyring") -> ( flow { typ = KeyRingFile }, op ) | ||
977 | Left ("type",Just "pem" ) -> ( flow { typ = PEMFile }, op ) | ||
978 | Left ("type",Just "wallet" ) -> ( flow { typ = WalletFile }, op ) | ||
979 | Left ("type",Just "hosts" ) -> ( flow { typ = Hosts }, op ) | ||
980 | Left ("access",Just "public") -> ( flow { access = Pub }, op ) | ||
981 | Left ("access",Just "secret") -> ( flow { access = Sec }, op ) | ||
982 | Left ("access",Just "auto") -> ( flow { access = AutoAccess }, op ) | ||
983 | Left ("home",mb) -> | ||
984 | ( flow | ||
985 | , op { opFiles = Map.insert HomePub flow { access=Pub } | ||
986 | $ Map.insert HomeSec flow { access=Sec } | ||
987 | $ opFiles op | ||
988 | , opHome = opHome op `mplus` mb | ||
989 | } | ||
990 | ) | ||
991 | Left ("flow",Just flowspec) -> | ||
992 | case parseFlow flowspec of | ||
993 | Just ( (fil,spil), mtch ) -> | ||
994 | ( updateFlow fil spil mtch flow | ||
995 | , op ) | ||
996 | Nothing -> error "Valid flow words are: spill,fill,sync,subkeys or match=KEYSPEC" | ||
997 | Left (option,_) -> error $ "Unrecognized option: " ++ option | ||
966 | 998 | ||
967 | splitArg :: String -> Either (String,Maybe String) String | 999 | splitArg :: String -> Either (String,Maybe String) String |
968 | splitArg arg = | 1000 | splitArg arg = |