Skip to content

Commit 799b43c

Browse files
committed
Enable filtering packages by distro
1 parent 7bfa6a2 commit 799b43c

File tree

5 files changed

+51
-38
lines changed

5 files changed

+51
-38
lines changed

datafiles/templates/Html/new-browse.html.st

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,8 @@
221221
<dd>Only show deprecated packages.</dd>
222222
<dt>(deprecated:false)</dt>
223223
<dd>Only show packages that are not deprecated. If no other deprecation filter is given, this filter is automatically added.</dd>
224+
<dt>(distro:Debian)</dt>
225+
<dd>Only show packages that are available in the Debian distribution. See the <a href="/distros">full list of available distributions</a>.</dd>
224226
</dl>
225227
</div>
226228
<table id=newBrowse class=fancy>

src/Distribution/Server/Features.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,7 @@ initHackageFeatures env@ServerEnv{serverVerbosity = verbosity} = do
333333
tagsFeature
334334
listFeature
335335
searchFeature
336+
distroFeature
336337

337338
#endif
338339

src/Distribution/Server/Features/Browse.hs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import qualified Data.Vector as V
1515
import Distribution.Server.Features.Browse.ApplyFilter (applyFilter)
1616
import Distribution.Server.Features.Browse.Options (BrowseOptions(..), IsSearch(..))
1717
import Distribution.Server.Features.Core (CoreFeature(CoreFeature), queryGetPackageIndex, coreResource)
18+
import Distribution.Server.Features.Distro (DistroFeature)
1819
import Distribution.Server.Features.PackageList (ListFeature(ListFeature), makeItemList)
1920
import Distribution.Server.Features.Search (SearchFeature(SearchFeature), searchPackages)
2021
import Distribution.Server.Features.Tags (TagsFeature(TagsFeature), tagsResource)
@@ -36,11 +37,12 @@ type BrowseFeature =
3637
-> TagsFeature
3738
-> ListFeature
3839
-> SearchFeature
40+
-> DistroFeature
3941
-> IO HackageFeature
4042

4143
initNewBrowseFeature :: ServerEnv -> IO BrowseFeature
4244
initNewBrowseFeature _env =
43-
pure \coreFeature userFeature tagsFeature listFeature searchFeature ->
45+
pure \coreFeature userFeature tagsFeature listFeature searchFeature distroFeature ->
4446
pure $
4547
(emptyHackageFeature "json")
4648
{ featureResources =
@@ -50,7 +52,7 @@ initNewBrowseFeature _env =
5052
]
5153
, resourcePost =
5254
[ ("json"
53-
, \_ -> getNewPkgList coreFeature userFeature tagsFeature listFeature searchFeature
55+
, \_ -> getNewPkgList coreFeature userFeature tagsFeature listFeature searchFeature distroFeature
5456
)
5557
]
5658
}
@@ -89,8 +91,8 @@ paginate PaginationConfig{totalNumberOfElements, pageNumber} = do
8991
else pageSize
9092
)
9193

92-
getNewPkgList :: CoreFeature -> UserFeature -> TagsFeature -> ListFeature -> SearchFeature -> ServerPartT (ExceptT ErrorResponse IO) Response
93-
getNewPkgList CoreFeature{queryGetPackageIndex, coreResource} UserFeature{userResource} TagsFeature{tagsResource} ListFeature{makeItemList} SearchFeature{searchPackages} = do
94+
getNewPkgList :: CoreFeature -> UserFeature -> TagsFeature -> ListFeature -> SearchFeature -> DistroFeature -> ServerPartT (ExceptT ErrorResponse IO) Response
95+
getNewPkgList CoreFeature{queryGetPackageIndex, coreResource} UserFeature{userResource} TagsFeature{tagsResource} ListFeature{makeItemList} SearchFeature{searchPackages} distroFeature = do
9496
browseOptionsBS <- lookBS "browseOptions"
9597
browseOptions <- lift (parseBrowseOptions browseOptionsBS)
9698
(isSearch, packageNames) <-
@@ -99,8 +101,8 @@ getNewPkgList CoreFeature{queryGetPackageIndex, coreResource} UserFeature{userRe
99101
terms -> (IsSearch,) <$> liftIO (searchPackages terms)
100102
pkgDetails <- liftIO (makeItemList packageNames)
101103
now <- liftIO getCurrentTime
102-
let listOfPkgs = applyFilter now isSearch coreResource userResource tagsResource browseOptions pkgDetails
103-
config =
104+
listOfPkgs <- liftIO $ applyFilter now isSearch coreResource userResource tagsResource distroFeature browseOptions pkgDetails
105+
let config =
104106
PaginationConfig
105107
{ totalNumberOfElements = length listOfPkgs
106108
, pageNumber = fromIntegral $ boPage browseOptions

src/Distribution/Server/Features/Browse/ApplyFilter.hs

Lines changed: 37 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{-# LANGUAGE RecordWildCards, NamedFieldPuns, TypeApplications #-}
22
module Distribution.Server.Features.Browse.ApplyFilter (applyFilter) where
33

4+
import Control.Monad (filterM)
45
import Data.List (sortBy)
56
import Data.Ord (comparing)
67
import Data.Time.Clock (UTCTime(utctDay), diffUTCTime)
@@ -13,18 +14,21 @@ import qualified Data.Set as S
1314
import Distribution.Server.Features.Browse.Options (BrowseOptions(..), Direction(..), Column(..), Sort(..), NormalColumn(..), IsSearch(..))
1415
import Distribution.Server.Features.Browse.Parsers (DeprecatedOption(..), Filter(..), operatorToFunction)
1516
import Distribution.Server.Features.Core (CoreResource, corePackageNameUri)
17+
import Distribution.Server.Features.Distro (DistroFeature(DistroFeature, queryPackageStatus))
18+
import Distribution.Server.Features.Distro.Types (DistroName(..))
1619
import Distribution.Server.Features.PackageList(PackageItem(..))
1720
import Distribution.Server.Features.Tags (Tag(..), TagsResource, tagUri)
1821
import Distribution.Server.Features.Users (UserResource, userPageUri)
1922
import Distribution.Server.Users.Types (UserName)
2023
import Distribution.Text (display)
2124

22-
applyFilter :: UTCTime -> IsSearch -> CoreResource -> UserResource -> TagsResource -> BrowseOptions -> [PackageItem] -> [Value]
23-
applyFilter now isSearch coreResource userResource tagsResource browseOptions items =
24-
map packageIndexInfoToValue $
25-
sort isSearch (boSort browseOptions) $
26-
filterPackages now (boFilters browseOptions) $
27-
items
25+
applyFilter :: UTCTime -> IsSearch -> CoreResource -> UserResource -> TagsResource -> DistroFeature -> BrowseOptions -> [PackageItem] -> IO [Value]
26+
applyFilter now isSearch coreResource userResource tagsResource DistroFeature{queryPackageStatus} browseOptions items = do
27+
packages <- filterM filterForItem items
28+
pure $
29+
map packageIndexInfoToValue $
30+
sort isSearch (boSort browseOptions) $
31+
packages
2832
where
2933
packageIndexInfoToValue :: PackageItem -> Value
3034
packageIndexInfoToValue PackageItem{..} =
@@ -55,6 +59,33 @@ applyFilter now isSearch coreResource userResource tagsResource browseOptions it
5559
, T.pack "display" .= display pkg
5660
]
5761

62+
includeItem :: PackageItem -> Filter -> IO Bool
63+
includeItem PackageItem{ itemDownloads } (DownloadsFilter ( op, sndParam)) = pure $ operatorToFunction op (fromIntegral @Int @Word itemDownloads) sndParam
64+
includeItem PackageItem{ itemVotes } (RatingFilter (op, sndParam) ) = pure $ operatorToFunction op itemVotes sndParam
65+
includeItem PackageItem{ itemLastUpload } (LastUploadFilter (op, sndParam)) = pure $ operatorToFunction op (utctDay itemLastUpload) sndParam
66+
includeItem PackageItem{ itemTags } (TagFilter tagStr) = pure $ any (\tag -> display tag == tagStr) itemTags
67+
includeItem PackageItem{ itemMaintainer } (MaintainerFilter maintainerStr) = pure $ any (\user -> display user == maintainerStr) itemMaintainer
68+
includeItem PackageItem{ itemLastUpload } (AgeLastULFilter (op, sndParam)) = pure $ operatorToFunction op (diffUTCTime now itemLastUpload) sndParam
69+
includeItem PackageItem{ itemDeprecated } (DeprecatedFilter OnlyDeprecated) = pure $ not (null itemDeprecated)
70+
includeItem PackageItem{ itemDeprecated } (DeprecatedFilter ExcludeDeprecated) = pure $ null itemDeprecated
71+
includeItem _ (DeprecatedFilter Don'tCareAboutDeprecated) = pure True
72+
includeItem PackageItem{ itemName } (DistroFilter distroStr) = elem (DistroName distroStr) . map fst <$> queryPackageStatus itemName
73+
includeItem packageItem (Not filt) = not <$> includeItem packageItem filt
74+
75+
filtersWithoutDefaults = boFilters browseOptions
76+
77+
filtersWithDefaults =
78+
-- The lack of other filters means we don't care.
79+
-- But deprecated packages are excluded by default.
80+
-- So we check if the user has overriden the default filter.
81+
case [ x | DeprecatedFilter x <- filtersWithoutDefaults ] of
82+
[] -> DeprecatedFilter ExcludeDeprecated : filtersWithoutDefaults
83+
_ -> filtersWithoutDefaults
84+
85+
filterForItem :: PackageItem -> IO Bool
86+
filterForItem item =
87+
all id <$> traverse (includeItem item) filtersWithDefaults
88+
5889
sort :: IsSearch -> Sort -> [PackageItem] -> [PackageItem]
5990
sort isSearch Sort {sortColumn, sortDirection} =
6091
case sortColumn of
@@ -79,28 +110,3 @@ sort isSearch Sort {sortColumn, sortDirection} =
79110
case sortDirection of
80111
Ascending -> id
81112
Descending -> flip
82-
83-
includeItem :: UTCTime -> PackageItem -> Filter -> Bool
84-
includeItem _ PackageItem{ itemDownloads } (DownloadsFilter ( op, sndParam)) = operatorToFunction op (fromIntegral @Int @Word itemDownloads) sndParam
85-
includeItem _ PackageItem{ itemVotes } (RatingFilter (op, sndParam) ) = operatorToFunction op itemVotes sndParam
86-
includeItem _ PackageItem{ itemLastUpload } (LastUploadFilter (op, sndParam)) = operatorToFunction op (utctDay itemLastUpload) sndParam
87-
includeItem _ PackageItem{ itemTags } (TagFilter tagStr) = any (\tag -> display tag == tagStr) itemTags
88-
includeItem _ PackageItem{ itemMaintainer } (MaintainerFilter maintainerStr) = any (\user -> display user == maintainerStr) itemMaintainer
89-
includeItem now PackageItem{ itemLastUpload } (AgeLastULFilter (op, sndParam)) = operatorToFunction op (diffUTCTime now itemLastUpload) sndParam
90-
includeItem _ PackageItem{ itemDeprecated } (DeprecatedFilter OnlyDeprecated) = not (null itemDeprecated)
91-
includeItem _ PackageItem{ itemDeprecated } (DeprecatedFilter ExcludeDeprecated) = null itemDeprecated
92-
includeItem _ _ (DeprecatedFilter Don'tCareAboutDeprecated) = True
93-
includeItem now packageItem (Not filt) = not (includeItem now packageItem filt)
94-
95-
filterPackages :: UTCTime -> [Filter] -> [PackageItem] -> [PackageItem]
96-
filterPackages now filtersWithoutDefaults = filter filterForItem
97-
where
98-
filterForItem :: PackageItem -> Bool
99-
filterForItem item = all (includeItem now item) filtersWithDefaults
100-
filtersWithDefaults =
101-
-- The lack of other filters means we don't care.
102-
-- But deprecated packages are excluded by default.
103-
-- So we check if the user has overriden the default filter.
104-
case [ x | DeprecatedFilter x <- filtersWithoutDefaults ] of
105-
[] -> DeprecatedFilter ExcludeDeprecated : filtersWithoutDefaults
106-
_ -> filtersWithoutDefaults

src/Distribution/Server/Features/Browse/Parsers.hs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ data Filter
3636
| TagFilter String
3737
| MaintainerFilter String
3838
| DeprecatedFilter DeprecatedOption
39+
| DistroFilter String
3940
| Not Filter
4041
deriving (Show, Eq)
4142

@@ -84,7 +85,7 @@ allowedAfterOpeningBrace AllowNot = "not " <|> allowedAfterOpeningBrace Disallow
8485
allowedAfterOpeningBrace _ =
8586
asum
8687
[ "downloads", "rating", "lastUpload" , "ageOfLastUpload"
87-
, "tag:", "maintainer:", "deprecated:"
88+
, "tag:", "maintainer:", "deprecated:", "distro:"
8889
]
8990

9091
-- Whether the 'not' operator can be used.
@@ -111,6 +112,7 @@ filterWith allowNot = do
111112
"tag:" -> TagFilter <$> wordWoSpaceOrParens
112113
"maintainer:" -> MaintainerFilter <$> wordWoSpaceOrParens
113114
"deprecated:" -> DeprecatedFilter <$> deprecatedOption
115+
"distro:" -> DistroFilter <$> wordWoSpaceOrParens
114116
_ -> fail "Impossible since fieldName possibilities are known at compile time"
115117
pure filt
116118

0 commit comments

Comments
 (0)