@@ -18,14 +18,19 @@ module Distribution.Gentoo.CmdLine
18
18
) where
19
19
20
20
import Control.Monad ((>=>) )
21
+ import qualified Data.List.NonEmpty as NE
22
+ import Data.Monoid (Ap (.. ))
23
+ import Data.Maybe (fromMaybe )
21
24
import Data.Proxy
25
+ import Data.Semigroup (Last (.. ), sconcat )
22
26
import System.Console.GetOpt
23
27
24
28
import Distribution.Gentoo.CmdLine.Types
25
29
import Distribution.Gentoo.PkgManager
26
30
import Distribution.Gentoo.PkgManager.Types
27
31
import Distribution.Gentoo.Types
28
32
import qualified Distribution.Gentoo.Types.HUMode as Mode
33
+ import Distribution.Gentoo.Util (These (.. ), singletonNE )
29
34
import Output
30
35
31
36
-- | Process arguments from the command line. Returns an error string if the
@@ -59,13 +64,15 @@ mkHUMode cmdLine raw
59
64
-- Logic for parsing modes for non-portage package managers
60
65
mkMode :: RunMode -> Either String Mode. RunMode
61
66
mkMode = \ case
62
- BasicMode -> Mode. BasicMode <$> mkTarget (cmdLineTarget cmdLine)
63
- ListMode -> Mode. ListMode <$> mkTarget (cmdLineTarget cmdLine)
67
+ BasicMode -> Mode. BasicMode <$> go (cmdLineTargets cmdLine)
68
+ ListMode -> Mode. ListMode <$> go (cmdLineTargets cmdLine)
64
69
ReinstallAtomsMode -> Left
65
70
" reinstall-atoms mode is only supported by the portage package manager"
71
+ where
72
+ go = maybe (Right Mode. OnlyInvalid ) (onlyLast mkTarget)
66
73
67
74
-- Logic for parsing targets for non-portage package managers
68
- mkTarget :: Either CustomTargets BuildTarget -> Either String Mode. Target
75
+ mkTarget :: Either CustomTarget BuildTarget -> Either String Mode. Target
69
76
mkTarget = \ case
70
77
Right OnlyInvalid -> Right Mode. OnlyInvalid
71
78
Right AllInstalled -> Right Mode. AllInstalled
@@ -83,36 +90,42 @@ mkHUMode cmdLine raw
83
90
-> Either String Mode. PortageMode
84
91
mkPortageMode = \ case
85
92
BasicMode -> Mode. PortageBasicMode
86
- <$> mkPortageBasicTarget (cmdLineTarget cmdLine)
93
+ <$> withDefTarget
94
+ (onlyLast mkPortageBasicTarget)
95
+ maybeTargs
87
96
ListMode -> Mode. PortageListMode
88
- <$> mkPortageTarget (cmdLineTarget cmdLine)
97
+ <$> withDefTarget
98
+ (onlyLast mkPortageTarget)
99
+ maybeTargs
89
100
ReinstallAtomsMode -> Mode. ReinstallAtomsMode
90
- <$> mkPortageRATarget (cmdLineTarget cmdLine)
101
+ <$> withDefTarget mkPortageRATarget maybeTargs
102
+ where
103
+ maybeTargs = cmdLineTargets cmdLine
91
104
92
105
-- Logic for parsing targets for portage's basic mode
93
106
mkPortageBasicTarget
94
- :: Either CustomTargets BuildTarget
107
+ :: Either CustomTarget BuildTarget
95
108
-> Either String (Either Mode. PortageBasicTarget Mode. Target )
96
109
mkPortageBasicTarget = \ case
97
110
Right PreservedRebuild -> Right $ Left Mode. PreservedRebuild
98
111
targ -> Right <$> mkPortageTarget targ
99
112
100
113
-- Logic for parsing targets for portage's reinstall-atoms mode
101
114
mkPortageRATarget
102
- :: Either CustomTargets BuildTarget
103
- -> Either String (Either Mode. Target Mode. ReinstallAtomsTarget )
104
- mkPortageRATarget = \ case
105
- Right WorldTarget -> Right $ Right $
115
+ :: NE. NonEmpty (Either CustomTarget BuildTarget )
116
+ -> Either String Mode. RATargets
117
+ mkPortageRATarget = foldTargets $ \ case
118
+ Left ct -> Right $ That $ That $ singletonNE ct
119
+ Right WorldTarget -> Right $ That $ This $
106
120
if cmdLineWorldFull cmdLine
107
121
then Mode. WorldFullTarget
108
122
else Mode. WorldTarget
109
- Left cts -> Right $ Right $ Mode. CustomTargets cts
110
- targ -> Left <$> mkPortageTarget targ
123
+ targ -> This <$> mkPortageTarget targ
111
124
112
125
-- Logic for parsing targets for portage's list mode; also common logic
113
126
-- for parsing targets, between portage's basic and reinstall-atoms modes
114
127
mkPortageTarget
115
- :: Either CustomTargets BuildTarget
128
+ :: Either CustomTarget BuildTarget
116
129
-> Either String Mode. Target
117
130
mkPortageTarget = \ case
118
131
Right OnlyInvalid -> Right Mode. OnlyInvalid
@@ -135,6 +148,31 @@ mkHUMode cmdLine raw
135
148
, verbosity = cmdLineVerbosity cmdLine
136
149
}
137
150
151
+ -- Uses the default target if none were specified on the command line
152
+ withDefTarget
153
+ :: (NE. NonEmpty (Either CustomTarget BuildTarget ) -> a )
154
+ -> Maybe (NE. NonEmpty (Either CustomTarget BuildTarget ))
155
+ -> a
156
+ withDefTarget f = f . fromMaybe (NE. singleton defTarget)
157
+ where
158
+ defTarget = Right OnlyInvalid
159
+
160
+ -- Uses 'Data.Semigroup.Last' to only grab the last target specified
161
+ onlyLast
162
+ :: Applicative f
163
+ => (a -> f b )
164
+ -> NE. NonEmpty a
165
+ -> f b
166
+ onlyLast f = fmap (getLast . sconcat . fmap Last ) . traverse f
167
+
168
+ -- Uses 'Data.Monoid.Ap' to combine RATargets inside an Applicative
169
+ foldTargets
170
+ :: (Applicative f , Semigroup b )
171
+ => (a -> f b )
172
+ -> NE. NonEmpty a
173
+ -> f b
174
+ foldTargets f = getAp . sconcat . fmap (Ap . f)
175
+
138
176
options :: [OptDescr (CmdLineArgs -> Either String CmdLineArgs )]
139
177
options =
140
178
[ Option [' P' ] [" package-manager" ]
@@ -196,9 +234,8 @@ options =
196
234
}
197
235
)
198
236
" target" )
199
- $ " Use a custom target. May be given multiple times.\n "
200
- ++ " Enables portage PM and reinstall-targets mode.\n "
201
- ++ " Will override any non-custom targets."
237
+ " Use a custom target. May be given multiple times.\n \
238
+ \ Enables portage PM and reinstall-targets mode."
202
239
, Option [] [" mode" ]
203
240
(ReqArg (fromCmdline (\ a c -> c { cmdLineMode = a })) " mode" )
204
241
(argHelp (Proxy @ RunMode ))
@@ -237,18 +274,8 @@ options =
237
274
\ which can be overriden with the \" PACKAGE_MANAGER\"\n \
238
275
\ environment variable."
239
276
240
- -- Custom targets always override BuildTargets
241
- -- New custom targets are appended to old custom targets
242
- -- New BuildTargets override old BuildTargets
243
- updateTarget :: Either String BuildTarget -> CmdLineArgs -> CmdLineArgs
277
+ updateTarget :: Either CustomTarget BuildTarget -> CmdLineArgs -> CmdLineArgs
244
278
updateTarget new old =
245
- let newT = case (new, cmdLineTarget old) of
246
- -- Override old BuildTargets with new BuildTargets
247
- (Right t, Right _) -> Right t
248
- -- Append new custom target
249
- (Left s, Left ss) -> Left $ ss ++ [s]
250
- -- Drop old BuildTargets for new custom target
251
- (Left s, Right _) -> Left [s]
252
- -- Drop new BuildTargets in favor of old custom targets
253
- (Right _, Left ss) -> Left ss
254
- in old { cmdLineTarget = newT }
279
+ let ne = NE. singleton new
280
+ newT = maybe ne (<> ne) (cmdLineTargets old)
281
+ in old { cmdLineTargets = Just newT }
0 commit comments