| 1 | Fri Sep 25 00:27:01 CEST 2009 vandijk.roel@gmail.com |
|---|
| 2 | * Implemented reverse dependencies (#576) |
|---|
| 3 | |
|---|
| 4 | New patches: |
|---|
| 5 | |
|---|
| 6 | [Implemented reverse dependencies (#576) |
|---|
| 7 | vandijk.roel@gmail.com**20090924222701 |
|---|
| 8 | Ignore-this: f9e5e358a4c8db9d5ae17c47a1a49565 |
|---|
| 9 | ] { |
|---|
| 10 | hunk ./Locations.hs 63 |
|---|
| 11 | pkgScriptURL :: URL |
|---|
| 12 | pkgScriptURL = "/package" |
|---|
| 13 | |
|---|
| 14 | +-- URL of the CGI script to show reverse dependencies of a package |
|---|
| 15 | +pkgRevDepsURL :: URL |
|---|
| 16 | +pkgRevDepsURL = "/revdeps" |
|---|
| 17 | + |
|---|
| 18 | -- URL of the list of recent additions to the database |
|---|
| 19 | recentAdditionsURL :: URL |
|---|
| 20 | recentAdditionsURL = "/packages/archive/recent.html" |
|---|
| 21 | hunk ./Makefile 4 |
|---|
| 22 | SHELL = /bin/sh |
|---|
| 23 | HC = ghc |
|---|
| 24 | HCFLAGS = -O -Wall |
|---|
| 25 | -CGI_PROGS = upload-pkg check-pkg package search |
|---|
| 26 | -AUX_PROGS = pkg-list recent-adds rss-feed latest-versions splitDistroMap |
|---|
| 27 | +CGI_PROGS = upload-pkg check-pkg package revdeps search |
|---|
| 28 | +AUX_PROGS = pkg-list pkg-rev-deps recent-adds rss-feed latest-versions splitDistroMap |
|---|
| 29 | GEN_PROGS = $(CGI_PROGS) $(AUX_PROGS) |
|---|
| 30 | PROGS = $(GEN_PROGS) post-upload-hook preferred-versions |
|---|
| 31 | |
|---|
| 32 | hunk ./Makefile 29 |
|---|
| 33 | install: $(PROGS) |
|---|
| 34 | scp -C $(PROGS) $(HACKAGE_HOST):$(TMPDIR) |
|---|
| 35 | ssh $(HACKAGE_HOST) mv $(TMPDIR)/package $(CGIDIR) |
|---|
| 36 | + ssh $(HACKAGE_HOST) mv $(TMPDIR)/revdeps $(CGIDIR) |
|---|
| 37 | ssh $(HACKAGE_HOST) mv $(TMPDIR)/check-pkg $(CGIDIR) |
|---|
| 38 | ssh $(HACKAGE_HOST) mv $(TMPDIR)/upload-pkg $(CGIDIR)/protected |
|---|
| 39 | ssh $(HACKAGE_HOST) mv $(TMPDIR)/search $(CGIDIR) |
|---|
| 40 | hunk ./Makefile 35 |
|---|
| 41 | ssh $(HACKAGE_HOST) mv $(TMPDIR)/post-upload-hook $(BINDIR) |
|---|
| 42 | ssh $(HACKAGE_HOST) mv $(TMPDIR)/pkg-list $(BINDIR) |
|---|
| 43 | + ssh $(HACKAGE_HOST) mv $(TMPDIR)/pkg-rev-deps $(BINDIR) |
|---|
| 44 | ssh $(HACKAGE_HOST) mv $(TMPDIR)/recent-adds $(BINDIR) |
|---|
| 45 | ssh $(HACKAGE_HOST) mv $(TMPDIR)/rss-feed $(BINDIR) |
|---|
| 46 | ssh $(HACKAGE_HOST) mv $(TMPDIR)/latest-versions $(BINDIR) |
|---|
| 47 | hunk ./Makefile 56 |
|---|
| 48 | $(HC) --make $(HCFLAGS) -o $@ package.hs |
|---|
| 49 | strip $@ |
|---|
| 50 | |
|---|
| 51 | +revdeps: revdeps.hs Locations.hs Util.hs RevDepsPage.hs |
|---|
| 52 | + $(HC) --make $(HCFLAGS) -o $@ revdeps.hs |
|---|
| 53 | + strip $@ |
|---|
| 54 | + |
|---|
| 55 | search: search.hs SearchAlgorithm.hs SearchMatchingFunctions.hs SearchUtils.hs SearchHackage.hs SearchTypes.hs Locations.hs Util.hs |
|---|
| 56 | $(HC) --make $(HCFLAGS) -o $@ search.hs |
|---|
| 57 | strip $@ |
|---|
| 58 | hunk ./Makefile 70 |
|---|
| 59 | $(HC) --make $(HCFLAGS) -o $@ pkg-list.hs |
|---|
| 60 | strip $@ |
|---|
| 61 | |
|---|
| 62 | +pkg-rev-deps: pkg-rev-deps.hs RevDepMap.hs Locations.hs Util.hs |
|---|
| 63 | + $(HC) --make $(HCFLAGS) -o $@ pkg-rev-deps.hs |
|---|
| 64 | + strip $@ |
|---|
| 65 | + |
|---|
| 66 | recent-adds: recent-adds.hs Locations.hs Util.hs |
|---|
| 67 | $(HC) --make $(HCFLAGS) -o $@ recent-adds.hs |
|---|
| 68 | strip $@ |
|---|
| 69 | hunk ./PackagePage.hs 7 |
|---|
| 70 | import Control.Monad ( guard, liftM2 ) |
|---|
| 71 | import qualified Data.Foldable as Foldable |
|---|
| 72 | import Data.Char ( toLower, toUpper, isSpace ) |
|---|
| 73 | -import Data.List ( delete, intersperse, isPrefixOf, |
|---|
| 74 | +import Data.List ( intersperse, isPrefixOf, |
|---|
| 75 | partition, sort, sortBy ) |
|---|
| 76 | import Data.Maybe |
|---|
| 77 | import Data.Map ( Map ) |
|---|
| 78 | hunk ./PackagePage.hs 28 |
|---|
| 79 | import Util ( cabalFile, packageFile, |
|---|
| 80 | dirContents, getDependencies, |
|---|
| 81 | availableVersions, maybeLast, packageURL, |
|---|
| 82 | - packageDir, splitOn, catLabel ) |
|---|
| 83 | + packageDir, splitOn, catLabel, |
|---|
| 84 | + getReverseDependencies, revDepsURL |
|---|
| 85 | + ) |
|---|
| 86 | import TagMap |
|---|
| 87 | import DistroInfo |
|---|
| 88 | |
|---|
| 89 | hunk ./PackagePage.hs 53 |
|---|
| 90 | , pdDependencies :: Map PackageName [Version] |
|---|
| 91 | -- ^ dependent packages from 'pdDescription', each paired |
|---|
| 92 | -- with available versions of that package (if any). |
|---|
| 93 | + , pdRevDeps :: [(PackageIdentifier, Int, Int, Bool)] |
|---|
| 94 | + -- ^ List of packages that depend on this package, the number |
|---|
| 95 | + -- of direct reverse dependencies per package, the number of |
|---|
| 96 | + -- indirect reverse dependencies per package and a flag |
|---|
| 97 | + -- indicating whether the package directly depends on the |
|---|
| 98 | + -- package in question. The first item in this list contains |
|---|
| 99 | + -- information about the original package. |
|---|
| 100 | , pdDocURL :: Maybe URL |
|---|
| 101 | -- ^ URL of Haddock documentation for this version of the |
|---|
| 102 | -- package (if available). |
|---|
| 103 | hunk ./PackagePage.hs 89 |
|---|
| 104 | vs <- availableVersions (pkgName pkgId) |
|---|
| 105 | |
|---|
| 106 | deps <- getDependencies pkg |
|---|
| 107 | + revDeps <- getReverseDependencies pkgId |
|---|
| 108 | |
|---|
| 109 | let htmldir = pkgDir `slash` "doc" `slash` "html" |
|---|
| 110 | docExists <- doesDirectoryExist $ localFile htmldir |
|---|
| 111 | hunk ./PackagePage.hs 106 |
|---|
| 112 | , pdTags = tags tag_map |
|---|
| 113 | , pdAllVersions = vs |
|---|
| 114 | , pdDependencies = deps |
|---|
| 115 | + , pdRevDeps = revDeps |
|---|
| 116 | , pdDocURL = mbHtmlURL |
|---|
| 117 | , pdBuilds = builds |
|---|
| 118 | , pdBuildFailures = failures |
|---|
| 119 | hunk ./PackagePage.hs 185 |
|---|
| 120 | (bold << display pversion) : |
|---|
| 121 | map linkVers later_vs))] ++ |
|---|
| 122 | [("Dependencies", html_deps_list)] ++ |
|---|
| 123 | + [("Reverse deps.", html_rev_deps)] ++ |
|---|
| 124 | [(fname, f_value) | |
|---|
| 125 | (fname, htmlField) <- showFields, |
|---|
| 126 | let f_value = htmlField pkg, |
|---|
| 127 | hunk ./PackagePage.hs 214 |
|---|
| 128 | intersperse (toHtml " " +++ bold (toHtml "or") +++ br) $ |
|---|
| 129 | map (showDependencies vmap) deps_list |
|---|
| 130 | deps_list = flatDependencies (pdDescription pd) |
|---|
| 131 | + html_rev_deps | null revDeps = toHtml "No reverse dependencies" |
|---|
| 132 | + | otherwise = concatHtml [ anchor ! [href $ revDepsURL pkgId ++ "#direct"] << |
|---|
| 133 | + (showStrong numD +++ toHtml " direct") |
|---|
| 134 | + , toHtml " and " |
|---|
| 135 | + , anchor ! [href $ revDepsURL pkgId ++ "#indirect"] << |
|---|
| 136 | + (showStrong numI +++ toHtml " indirect") |
|---|
| 137 | + , toHtml " dependencies on " |
|---|
| 138 | + , anchor ! [href $ revDepsURL pkgId] << |
|---|
| 139 | + toHtml (display pkgId) |
|---|
| 140 | + ] |
|---|
| 141 | + where ((_,numD,numI,_):_) = revDeps |
|---|
| 142 | + revDeps = pdRevDeps pd |
|---|
| 143 | successes = Map.keys (pdBuilds pd) |
|---|
| 144 | failures = Map.toList (Map.difference (pdBuildFailures pd) (pdBuilds pd)) |
|---|
| 145 | showLog (desc, url) = |
|---|
| 146 | hunk ./PackagePage.hs 242 |
|---|
| 147 | dispTagVal "superseded by" v = anchor ! [href (packageURL (PackageIdentifier (PackageName v) (Version [] [])))] << v |
|---|
| 148 | dispTagVal _ v = toHtml v |
|---|
| 149 | |
|---|
| 150 | +showStrong :: Show a => a -> Html |
|---|
| 151 | +showStrong = strong . toHtml . show |
|---|
| 152 | + |
|---|
| 153 | tabulate :: [(String, Html)] -> Html |
|---|
| 154 | -- tabulate items = dlist << concat [[dterm << t, ddef << d] | (t, d) <- items] |
|---|
| 155 | tabulate items = table ! [theclass "properties"] << |
|---|
| 156 | addfile ./RevDepMap.hs |
|---|
| 157 | hunk ./RevDepMap.hs 1 |
|---|
| 158 | +{-# LANGUAGE ScopedTypeVariables #-} |
|---|
| 159 | + |
|---|
| 160 | +module RevDepMap ( RevDepMap |
|---|
| 161 | + , calcRevDeps |
|---|
| 162 | + , lookup |
|---|
| 163 | + , latestVersions |
|---|
| 164 | + , totalRevDeps |
|---|
| 165 | + , totalRevDeps_st |
|---|
| 166 | + ) where |
|---|
| 167 | + |
|---|
| 168 | +import Control.Monad ( filterM, fmap, foldM, mapM ) |
|---|
| 169 | +import Control.Monad.ST ( ST, runST ) |
|---|
| 170 | +import Control.Monad.State.Lazy ( State, evalState, get, put ) |
|---|
| 171 | +import Data.Function ( on ) |
|---|
| 172 | +import Data.List ( nub, groupBy ) |
|---|
| 173 | +import Data.Maybe ( fromMaybe ) |
|---|
| 174 | +import Data.STRef ( STRef, newSTRef |
|---|
| 175 | + , readSTRef, writeSTRef |
|---|
| 176 | + ) |
|---|
| 177 | +import Distribution.Package ( Dependency(..) |
|---|
| 178 | + , PackageIdentifier(..) |
|---|
| 179 | + , PackageId |
|---|
| 180 | + , PackageName(..) |
|---|
| 181 | + ) |
|---|
| 182 | +import Distribution.Version ( withinRange ) |
|---|
| 183 | +import Prelude hiding ( lookup ) |
|---|
| 184 | + |
|---|
| 185 | +import qualified Data.Map as Mp |
|---|
| 186 | +import qualified Data.Set as S |
|---|
| 187 | + |
|---|
| 188 | + |
|---|
| 189 | +------------------------------------------------------------------------------- |
|---|
| 190 | +-- Types |
|---|
| 191 | + |
|---|
| 192 | +-- |A RevDepMap maps a package 'x' to a set of packages which depend |
|---|
| 193 | +-- on 'x' in some way. |
|---|
| 194 | +type RevDepMap = Mp.Map PackageId (S.Set PackageId) |
|---|
| 195 | + |
|---|
| 196 | +------------------------------------------------------------------------------- |
|---|
| 197 | + |
|---|
| 198 | +-- |Transforms a reverse dependency map so that it contains only the last |
|---|
| 199 | +-- versions of every reverse dependency. |
|---|
| 200 | +latestVersions :: RevDepMap -> RevDepMap |
|---|
| 201 | +latestVersions = fmap ( S.fromDistinctAscList |
|---|
| 202 | + . map maximum |
|---|
| 203 | + . groupBy ((==) `on` pkgName) |
|---|
| 204 | + . S.toAscList |
|---|
| 205 | + ) |
|---|
| 206 | + |
|---|
| 207 | +------------------------------------------------------------------------------- |
|---|
| 208 | +-- Direct reverse dependencies |
|---|
| 209 | + |
|---|
| 210 | +-- |Calculates the direct reverse dependencies of every package in the |
|---|
| 211 | +-- input list. |
|---|
| 212 | +calcRevDeps :: [(PackageId, [Dependency])] -> RevDepMap |
|---|
| 213 | +calcRevDeps pkgs = |
|---|
| 214 | + foldr (\(pkg, deps) -> |
|---|
| 215 | + -- Per package on which this package depends, add this package as a |
|---|
| 216 | + -- reverse dependency. |
|---|
| 217 | + foldr2 (foldr2 (addRevDep pkg) . depToPkgs) |
|---|
| 218 | + (nub deps) |
|---|
| 219 | + ) |
|---|
| 220 | + emptyRevDepMap |
|---|
| 221 | + pkgs |
|---|
| 222 | + where |
|---|
| 223 | + -- A variant of foldr with the list and the default value flipped. |
|---|
| 224 | + foldr2 :: (a -> b -> b) -> [a] -> b -> b |
|---|
| 225 | + foldr2 = flip . foldr |
|---|
| 226 | + |
|---|
| 227 | + {- |
|---|
| 228 | + -- If emptyRevDepMap is set to initRevDeps then the result of calcRevDeps |
|---|
| 229 | + -- will also contain packages with 0 reverse dependencies. |
|---|
| 230 | + initRevDeps :: RevDepMap |
|---|
| 231 | + initRevDeps = Mp.fromList [(pkg, S.empty) | (pkg, _) <- pkgs] |
|---|
| 232 | + -} |
|---|
| 233 | + |
|---|
| 234 | + emptyRevDepMap = Mp.empty -- initRevDeps |
|---|
| 235 | + |
|---|
| 236 | + addRevDep :: PackageId -> PackageId -> (RevDepMap -> RevDepMap) |
|---|
| 237 | + addRevDep src pkg = Mp.insertWith (const $ S.insert src) |
|---|
| 238 | + pkg |
|---|
| 239 | + $ S.singleton src |
|---|
| 240 | + |
|---|
| 241 | + -- List of packages matching the dependency. |
|---|
| 242 | + depToPkgs :: Dependency -> [PackageId] |
|---|
| 243 | + depToPkgs (Dependency pkg vrange) = |
|---|
| 244 | + maybe [] |
|---|
| 245 | + (filter (\depPkg -> withinRange (pkgVersion depPkg) vrange)) |
|---|
| 246 | + $ Mp.lookup pkg nameToPkg |
|---|
| 247 | + |
|---|
| 248 | + -- Maps a package name to ALL versions of the package in the database. |
|---|
| 249 | + nameToPkg :: Mp.Map PackageName [PackageId] |
|---|
| 250 | + nameToPkg = foldr ( \(pkg, _) -> Mp.insertWith (const (pkg :)) |
|---|
| 251 | + (pkgName pkg) |
|---|
| 252 | + [pkg] |
|---|
| 253 | + ) |
|---|
| 254 | + Mp.empty |
|---|
| 255 | + pkgs |
|---|
| 256 | + |
|---|
| 257 | +------------------------------------------------------------------------------- |
|---|
| 258 | +-- Total reverse dependencies (using Sets) |
|---|
| 259 | + |
|---|
| 260 | +-- |Transforms a direct reverse dependencies map into a total reverse |
|---|
| 261 | +-- dependencies map. |
|---|
| 262 | +totalRevDeps :: RevDepMap -> RevDepMap |
|---|
| 263 | +totalRevDeps mp = Mp.mapWithKey (const . lookupAll mp) mp |
|---|
| 264 | + |
|---|
| 265 | +lookup :: RevDepMap -> PackageId -> S.Set PackageId |
|---|
| 266 | +lookup mp k = fromMaybe S.empty $ Mp.lookup k mp |
|---|
| 267 | + |
|---|
| 268 | +lookupAll :: RevDepMap -> PackageId -> S.Set PackageId |
|---|
| 269 | +lookupAll = dfs . lookup |
|---|
| 270 | + |
|---|
| 271 | + |
|---|
| 272 | +-- |Depth first search |
|---|
| 273 | +-- Given a graph and a starting node this function finds all nodes reachable |
|---|
| 274 | +-- from that starting node. The graph is represented by a function from a node |
|---|
| 275 | +-- to a set of nodes reachable from that node. |
|---|
| 276 | +dfs :: forall a. Ord a => (a -> S.Set a) -> a -> S.Set a |
|---|
| 277 | +dfs g r = evalState (search r) $ S.singleton r |
|---|
| 278 | + where search :: a -> State (S.Set a) (S.Set a) |
|---|
| 279 | + search n = do visited <- get |
|---|
| 280 | + let new = S.difference (g n) visited |
|---|
| 281 | + put $ S.union visited new |
|---|
| 282 | + deep <- mapM search $ S.toList new |
|---|
| 283 | + return $ S.union (S.unions deep) new |
|---|
| 284 | + |
|---|
| 285 | + |
|---|
| 286 | +------------------------------------------------------------------------------- |
|---|
| 287 | +-- Total reverse dependencies (using the ST monad) |
|---|
| 288 | + |
|---|
| 289 | +-- |Transforms a direct reverse dependencies map into a total reverse |
|---|
| 290 | +-- dependencies map. It does this using an algorithm which is much more |
|---|
| 291 | +-- efficient than the one using Sets. |
|---|
| 292 | +totalRevDeps_st :: [PackageId] -> RevDepMap -> RevDepMap |
|---|
| 293 | +totalRevDeps_st universe mp = runST go |
|---|
| 294 | + where |
|---|
| 295 | + go :: forall s. ST s RevDepMap |
|---|
| 296 | + go = do -- refMap :: Mp.Map PackageId (STRef s Bool) |
|---|
| 297 | + refMap <- fmap Mp.fromList |
|---|
| 298 | + $ mapM (tagNode False) universe |
|---|
| 299 | + |
|---|
| 300 | + -- Like the original RevDepMap, except the collection of reverse |
|---|
| 301 | + -- dependencies is represented by a list and associated with a |
|---|
| 302 | + -- tag. |
|---|
| 303 | + let tagged :: Mp.Map PackageId [(PackageId, STRef s Bool)] |
|---|
| 304 | + tagged = Mp.map (map (\x -> (x, refMap Mp.! x)) . S.toList) |
|---|
| 305 | + mp |
|---|
| 306 | + |
|---|
| 307 | + -- Calculate the total reverse dependencies by performing a depth |
|---|
| 308 | + -- first search per package and inserting the results in a newly |
|---|
| 309 | + -- constructed map. |
|---|
| 310 | + totalMp <- foldM (\mp' pkgId -> do |
|---|
| 311 | + -- Mark the initial node. |
|---|
| 312 | + writeSTRef (refMap Mp.! pkgId) True |
|---|
| 313 | + -- Calculate total reverse dependencies for current pkgId. |
|---|
| 314 | + revDeps <- dfs_st (\n -> fromMaybe [] $ Mp.lookup n tagged) pkgId |
|---|
| 315 | + -- Reset all tags for the next package. |
|---|
| 316 | + mapM_ (\r -> writeSTRef r False) $ Mp.elems refMap |
|---|
| 317 | + return $ Mp.insert pkgId (S.fromList revDeps) mp' |
|---|
| 318 | + ) |
|---|
| 319 | + Mp.empty |
|---|
| 320 | + $ Mp.keys mp |
|---|
| 321 | + |
|---|
| 322 | + return totalMp |
|---|
| 323 | + |
|---|
| 324 | + tagNode :: t -> n -> ST s (n, STRef s t) |
|---|
| 325 | + tagNode t n = newSTRef t >>= \r -> return (n, r) |
|---|
| 326 | + |
|---|
| 327 | + |
|---|
| 328 | +-- |Depth first search |
|---|
| 329 | +-- Given a graph and a starting node this function finds all nodes reachable |
|---|
| 330 | +-- from that starting node. The graph is represented by a function from a node |
|---|
| 331 | +-- to a list of nodes reachable from that node. Each node in that list is |
|---|
| 332 | +-- associated with a mutable variable which marks whether that node was visited |
|---|
| 333 | +-- before. |
|---|
| 334 | +-- Precondition: All nodes are unmarked. |
|---|
| 335 | +dfs_st :: forall a s. (a -> [(a, STRef s Bool)]) -> a -> ST s [a] |
|---|
| 336 | +dfs_st g r = search r |
|---|
| 337 | + where search :: a -> ST s [a] |
|---|
| 338 | + search n = do new <- fmap (map fst) . filterM checkAndMark $ g n |
|---|
| 339 | + deep <- mapM search new |
|---|
| 340 | + return $ new ++ concat deep |
|---|
| 341 | + |
|---|
| 342 | + checkAndMark :: (a, STRef s Bool) -> ST s Bool |
|---|
| 343 | + checkAndMark (_, ref) = do b <- readSTRef ref |
|---|
| 344 | + if b |
|---|
| 345 | + then return False |
|---|
| 346 | + else writeSTRef ref True >> return True |
|---|
| 347 | addfile ./RevDepsPage.hs |
|---|
| 348 | hunk ./RevDepsPage.hs 1 |
|---|
| 349 | +-- Body of the HTML page for the reverse dependencies of a package |
|---|
| 350 | +module RevDepsPage (getPkgRevDepsBody) where |
|---|
| 351 | + |
|---|
| 352 | +import Data.Function ( on ) |
|---|
| 353 | +import Data.List ( intersperse, sortBy, takeWhile, dropWhile ) |
|---|
| 354 | +import Distribution.Package ( PackageIdentifier(..), PackageId ) |
|---|
| 355 | +import Distribution.Text ( display ) |
|---|
| 356 | +import Distribution.Version ( Version ) |
|---|
| 357 | +import Text.XHtml |
|---|
| 358 | +import Util ( availableVersions, packageURL, revDepsURL |
|---|
| 359 | + , getReverseDependencies |
|---|
| 360 | + ) |
|---|
| 361 | + |
|---|
| 362 | + |
|---|
| 363 | +getPkgRevDepsBody :: PackageId -> IO [Html] |
|---|
| 364 | +getPkgRevDepsBody pkgId = do vs <- availableVersions (pkgName pkgId) |
|---|
| 365 | + revDeps <- getReverseDependencies pkgId |
|---|
| 366 | + return $ pkgRevDepsBody pkgId vs revDeps |
|---|
| 367 | + |
|---|
| 368 | +pkgRevDepsBody :: PackageId -> [Version] -> [(PackageId, Int, Int, Bool)] -> [Html] |
|---|
| 369 | +pkgRevDepsBody pkgId vs revDeps = (h2 << pageTitle) |
|---|
| 370 | + : paragraph << |
|---|
| 371 | + anchor ! [href $ packageURL pkgId] << |
|---|
| 372 | + toHtml "Package description" |
|---|
| 373 | + : go revDeps |
|---|
| 374 | + where |
|---|
| 375 | + pageTitle = "Reverse Dependencies of " ++ display (pkgName pkgId) |
|---|
| 376 | + |
|---|
| 377 | + go [] = noRevDeps |
|---|
| 378 | + go [_] = noRevDeps |
|---|
| 379 | + go (x:xs) = withRevDeps x $ sortDeps xs |
|---|
| 380 | + |
|---|
| 381 | + noRevDeps = [toHtml "No reverse dependencies"] |
|---|
| 382 | + |
|---|
| 383 | + withRevDeps x xs = overviewSection x vs |
|---|
| 384 | + : directRevDepSection pkgId xs |
|---|
| 385 | + ++ indirectRevDepSection pkgId xs |
|---|
| 386 | + |
|---|
| 387 | + sortDeps = sortBy (flip compare `on` (\(_,numD,numI,_) -> numD + numI)) |
|---|
| 388 | + |
|---|
| 389 | + |
|---|
| 390 | +overviewSection :: (PackageId, Int, Int, Bool) -> [Version] -> Html |
|---|
| 391 | +overviewSection (pkgId, numD, numI, _) vs = |
|---|
| 392 | + table << |
|---|
| 393 | + [ tr ! [theclass "odd"] << |
|---|
| 394 | + [ th ! [theclass "horizontal"] << |
|---|
| 395 | + if null earlier_vs && null later_vs then "Version" else "Versions" |
|---|
| 396 | + , td << commaList (map linkVers earlier_vs |
|---|
| 397 | + ++ ((strong << display pversion) : map linkVers later_vs)) |
|---|
| 398 | + ] |
|---|
| 399 | + , tr ! [theclass "even"] << |
|---|
| 400 | + [ th ! [theclass "horizontal"] << "Direct reverse deps." |
|---|
| 401 | + , td << anchor ! [href "#direct"] << toHtml (show numD) |
|---|
| 402 | + ] |
|---|
| 403 | + , tr ! [theclass "odd"] << |
|---|
| 404 | + [ th ! [theclass "horizontal"] << "Indirect reverse deps." |
|---|
| 405 | + , td << anchor ! [href "#indirect"] << toHtml (show numI) |
|---|
| 406 | + ] |
|---|
| 407 | + ] |
|---|
| 408 | + where |
|---|
| 409 | + pversion = pkgVersion pkgId |
|---|
| 410 | + pname = pkgName pkgId |
|---|
| 411 | + |
|---|
| 412 | + earlier_vs = takeWhile (< pversion) vs |
|---|
| 413 | + later_vs = dropWhile (<= pversion) vs |
|---|
| 414 | + |
|---|
| 415 | + linkVers v = anchor ! [href (revDepsURL (PackageIdentifier pname v))] << |
|---|
| 416 | + display v |
|---|
| 417 | + |
|---|
| 418 | +directRevDepSection :: PackageId -> [(PackageId, Int, Int, Bool)] -> [Html] |
|---|
| 419 | +directRevDepSection pkgId xs = |
|---|
| 420 | + revDepSection xs |
|---|
| 421 | + True |
|---|
| 422 | + "direct" |
|---|
| 423 | + "Direct reverse dependencies" |
|---|
| 424 | + $ concatHtml [ toHtml "A package is a direct reverse dependency of " |
|---|
| 425 | + , packageLink pkgId |
|---|
| 426 | + , toHtml " if it directly depend on " |
|---|
| 427 | + , packageLink pkgId |
|---|
| 428 | + ] |
|---|
| 429 | + |
|---|
| 430 | +indirectRevDepSection :: PackageId -> [(PackageId, Int, Int, Bool)] -> [Html] |
|---|
| 431 | +indirectRevDepSection pkgId xs = |
|---|
| 432 | + revDepSection xs |
|---|
| 433 | + False |
|---|
| 434 | + "indirect" |
|---|
| 435 | + "Indirect reverse dependencies" |
|---|
| 436 | + $ concatHtml [ toHtml "A package is an indirect reverse dependency of " |
|---|
| 437 | + , packageLink pkgId |
|---|
| 438 | + , toHtml " if it depends on either a direct reverse dependency or an indirect reverse dependency of " |
|---|
| 439 | + , packageLink pkgId |
|---|
| 440 | + ] |
|---|
| 441 | + |
|---|
| 442 | +revDepSection :: [(PackageId, Int, Int, Bool)] -> Bool -> String -> String -> Html -> [Html] |
|---|
| 443 | +revDepSection revDeps direct sname sectionTitle desc |
|---|
| 444 | + | null filteredRevDeps = [sectionAnchor] |
|---|
| 445 | + | otherwise = [ sectionAnchor |
|---|
| 446 | + , h3 << sectionTitle |
|---|
| 447 | + , paragraph << desc |
|---|
| 448 | + , revDepList filteredRevDeps |
|---|
| 449 | + ] |
|---|
| 450 | + where |
|---|
| 451 | + filteredRevDeps = filterOnDirect direct revDeps |
|---|
| 452 | + |
|---|
| 453 | + filterOnDirect :: Bool -> [(PackageId, Int, Int, Bool)] -> [(PackageId, Int, Int)] |
|---|
| 454 | + filterOnDirect x = map (\(pkgId, numD, numI, _) -> (pkgId, numD, numI)) |
|---|
| 455 | + . filter (\(_,_,_,isD) -> isD == x) |
|---|
| 456 | + |
|---|
| 457 | + sectionAnchor = anchor ! [name sname] << noHtml |
|---|
| 458 | + |
|---|
| 459 | +revDepList :: [(PackageId, Int, Int)] -> Html |
|---|
| 460 | +revDepList deps = |
|---|
| 461 | + table << |
|---|
| 462 | + ( tr << [ th << stringToHtml "Package" |
|---|
| 463 | + , th << stringToHtml "Direct" |
|---|
| 464 | + , th << stringToHtml "Indirect" |
|---|
| 465 | + ] |
|---|
| 466 | + : [ tr ! [theclass $ rowClass row] << |
|---|
| 467 | + [ td << packageLink depPkgId |
|---|
| 468 | + , td << revDepsLink depPkgId "#direct" (toHtml $ show numD) |
|---|
| 469 | + , td << revDepsLink depPkgId "#indirect" (toHtml $ show numI) |
|---|
| 470 | + ] |
|---|
| 471 | + | (row, (depPkgId, numD, numI)) <- zip [1..] deps |
|---|
| 472 | + ] |
|---|
| 473 | + ) |
|---|
| 474 | + |
|---|
| 475 | +packageLink :: PackageId -> Html |
|---|
| 476 | +packageLink pkgId = anchor ! [href $ packageURL pkgId] << |
|---|
| 477 | + toHtml (display pkgId) |
|---|
| 478 | + |
|---|
| 479 | +revDepsLink :: PackageId -> String -> Html -> Html |
|---|
| 480 | +revDepsLink pkgId extra contents = anchor ! [href $ revDepsURL pkgId ++ extra] << contents |
|---|
| 481 | + |
|---|
| 482 | +rowClass :: Int -> String |
|---|
| 483 | +rowClass n | odd n = "odd" |
|---|
| 484 | + | otherwise = "even" |
|---|
| 485 | + |
|---|
| 486 | +-- Copied from PackagePage |
|---|
| 487 | +commaList :: [Html] -> Html |
|---|
| 488 | +commaList = concatHtml . intersperse (toHtml ", ") |
|---|
| 489 | hunk ./Util.hs 4 |
|---|
| 490 | module Util where |
|---|
| 491 | |
|---|
| 492 | import Control.Exception ( bracket ) |
|---|
| 493 | -import Control.Monad ( unless, filterM, liftM ) |
|---|
| 494 | +import Control.Monad ( unless, filterM, liftM, guard ) |
|---|
| 495 | import Data.Bits ( (.&.), complement ) |
|---|
| 496 | import Data.Char ( isSpace, toLower ) |
|---|
| 497 | import Data.List ( (\\), sort ) |
|---|
| 498 | hunk ./Util.hs 10 |
|---|
| 499 | import Data.Map ( Map ) |
|---|
| 500 | import qualified Data.Map as Map |
|---|
| 501 | -import Data.Maybe ( listToMaybe ) |
|---|
| 502 | +import Data.Maybe ( listToMaybe, fromMaybe ) |
|---|
| 503 | import qualified Data.Set as Set ( fromList, toList ) |
|---|
| 504 | import Distribution.Compat.ReadP( readP_to_S ) |
|---|
| 505 | import Distribution.Package ( PackageName(..), PackageIdentifier(..), |
|---|
| 506 | hunk ./Util.hs 31 |
|---|
| 507 | import Text.XHtml ( URL ) |
|---|
| 508 | |
|---|
| 509 | import PublicFile |
|---|
| 510 | -import Locations ( archiveDir, pkgScriptURL ) |
|---|
| 511 | +import Locations ( archiveDir, pkgScriptURL, pkgRevDepsURL ) |
|---|
| 512 | |
|---|
| 513 | -- | Registered top-level nodes in the class hierarchy. |
|---|
| 514 | allocatedTopLevelNodes :: [String] |
|---|
| 515 | hunk ./Util.hs 48 |
|---|
| 516 | packageNameURL :: PackageName -> URL |
|---|
| 517 | packageNameURL pkg = pkgScriptURL ++ "/" ++ display pkg |
|---|
| 518 | |
|---|
| 519 | +-- | URL describing the reverse dependencies of a package, including version. |
|---|
| 520 | +revDepsURL :: PackageIdentifier -> URL |
|---|
| 521 | +revDepsURL pkgId = pkgRevDepsURL ++ "/" ++ display pkgId |
|---|
| 522 | + |
|---|
| 523 | +-- | URL describing the cached reverse dependencies of a package. |
|---|
| 524 | +revDepsFile :: PackageIdentifier -> PublicFile |
|---|
| 525 | +revDepsFile pkgId = packageDir pkgId `slash` "revdeps.csv" |
|---|
| 526 | + |
|---|
| 527 | -- package utilities |
|---|
| 528 | |
|---|
| 529 | -- | Available versions (if any) for each package mentioned in this one. |
|---|
| 530 | hunk ./Util.hs 76 |
|---|
| 531 | vs <- availableVersions n |
|---|
| 532 | return (n, vs) |
|---|
| 533 | |
|---|
| 534 | +-- | List of packages that depend on this one. |
|---|
| 535 | +getReverseDependencies :: PackageIdentifier -> IO [(PackageIdentifier, Int, Int, Bool)] |
|---|
| 536 | +getReverseDependencies pkgId = do hasRevDeps <- doesFileExist fp |
|---|
| 537 | + if hasRevDeps |
|---|
| 538 | + then do revDepFile <- readFile fp |
|---|
| 539 | + let xs = lines revDepFile |
|---|
| 540 | + return . fromMaybe [] . sequence $ map parseLine xs |
|---|
| 541 | + else return [] |
|---|
| 542 | + where |
|---|
| 543 | + -- This could be made much simpler by using functions from the "split" package. |
|---|
| 544 | + parseLine :: String -> Maybe (PackageIdentifier, Int, Int, Bool) |
|---|
| 545 | + parseLine l = do let (pname, rest1) = spanTillComma l |
|---|
| 546 | + guard (not $ null rest1) |
|---|
| 547 | + let (direct, rest2) = spanTillComma (tail rest1) |
|---|
| 548 | + guard (not $ null rest2) |
|---|
| 549 | + let (indirect, rest3) = spanTillComma (tail rest2) |
|---|
| 550 | + guard (not $ null rest3) |
|---|
| 551 | + let isDirect = tail rest3 |
|---|
| 552 | + guard (isDirect `elem` ["D", "I"]) |
|---|
| 553 | + let xs = readP_to_S parse pname |
|---|
| 554 | + guard ( not (null xs) |
|---|
| 555 | + && length direct > 0 |
|---|
| 556 | + && length indirect > 0 |
|---|
| 557 | + ) |
|---|
| 558 | + return ( fst $ last xs |
|---|
| 559 | + , read direct |
|---|
| 560 | + , read indirect |
|---|
| 561 | + , isDirect == "D" |
|---|
| 562 | + ) |
|---|
| 563 | + spanTillComma = span (/= ',') |
|---|
| 564 | + fp = localFile $ revDepsFile pkgId |
|---|
| 565 | + |
|---|
| 566 | -- | All package names available in the archive |
|---|
| 567 | availablePackages :: IO [PackageName] |
|---|
| 568 | availablePackages = do |
|---|
| 569 | hunk ./hackage-scripts.cabal 30 |
|---|
| 570 | other-modules: HaddockLex HaddockParse HaddockHtml HackagePage |
|---|
| 571 | Locations ModuleForest PackagePage Unpack Util |
|---|
| 572 | |
|---|
| 573 | +executable: revdeps |
|---|
| 574 | +main-is: revdeps.hs |
|---|
| 575 | +other-modules: Locations RevDepsPage Util |
|---|
| 576 | + |
|---|
| 577 | executable: search |
|---|
| 578 | main-is: search.hs |
|---|
| 579 | other-modules: SearchAlgorithm SearchMatchingFunctions SearchUtils |
|---|
| 580 | hunk ./hackage-scripts.cabal 50 |
|---|
| 581 | executable: rss-feed |
|---|
| 582 | main-is: rss-feed.hs |
|---|
| 583 | other-modules: Locations Util |
|---|
| 584 | + |
|---|
| 585 | +executable: pkg-rev-deps |
|---|
| 586 | +main-is: pkg-rev-deps.hs |
|---|
| 587 | +other-modules: Util |
|---|
| 588 | addfile ./pkg-rev-deps.hs |
|---|
| 589 | hunk ./pkg-rev-deps.hs 1 |
|---|
| 590 | +-- Generate a .csv file in every package directory containing the |
|---|
| 591 | +-- reverse dependencies of that package. |
|---|
| 592 | + |
|---|
| 593 | +module Main where |
|---|
| 594 | + |
|---|
| 595 | +import Control.Monad ( fmap, mapM ) |
|---|
| 596 | +import Data.List ( intercalate ) |
|---|
| 597 | +import Distribution.Package ( Dependency(..) |
|---|
| 598 | + , PackageIdentifier(..) |
|---|
| 599 | + , PackageId |
|---|
| 600 | + , PackageName(..) |
|---|
| 601 | + ) |
|---|
| 602 | +import Distribution.PackageDescription ( PackageDescription(..) ) |
|---|
| 603 | +import Distribution.PackageDescription.Configuration |
|---|
| 604 | + ( flattenPackageDescription ) |
|---|
| 605 | +import Distribution.Text ( display ) |
|---|
| 606 | +import PublicFile ( PublicFile, localFile ) |
|---|
| 607 | +import System.IO ( writeFile ) |
|---|
| 608 | +import Util ( availablePackages |
|---|
| 609 | + , availableVersions |
|---|
| 610 | + , loadPackageDescription |
|---|
| 611 | + , revDepsFile |
|---|
| 612 | + ) |
|---|
| 613 | + |
|---|
| 614 | +import qualified Data.Map as Mp |
|---|
| 615 | +import qualified Data.Set as S |
|---|
| 616 | +import qualified RevDepMap as RD |
|---|
| 617 | + |
|---|
| 618 | +------------------------------------------------------------------------------- |
|---|
| 619 | +-- Main |
|---|
| 620 | + |
|---|
| 621 | +main :: IO () |
|---|
| 622 | +main = do pkgs <- allPackages |
|---|
| 623 | + let revDepMap = RD.calcRevDeps pkgs |
|---|
| 624 | + directRevDeps = RD.latestVersions revDepMap |
|---|
| 625 | + -- Reference implementation, but much slower than the ST monad version. |
|---|
| 626 | + -- allRevDeps = RD.latestVersions $ RD.totalRevDeps revDepMap |
|---|
| 627 | + allRevDeps = RD.latestVersions $ RD.totalRevDeps_st (map fst pkgs) revDepMap |
|---|
| 628 | + writeRevDepFiles directRevDeps allRevDeps |
|---|
| 629 | + |
|---|
| 630 | +------------------------------------------------------------------------------- |
|---|
| 631 | + |
|---|
| 632 | +allPackages :: IO [(PackageId, [Dependency])] |
|---|
| 633 | +allPackages = do pkgNames <- availablePackages |
|---|
| 634 | + pkgDescs <- mapM availablePkgs pkgNames |
|---|
| 635 | + return $ concat pkgDescs |
|---|
| 636 | + |
|---|
| 637 | +availablePkgIds :: PackageName -> IO [PackageId] |
|---|
| 638 | +availablePkgIds p = fmap (map $ PackageIdentifier p) $ availableVersions p |
|---|
| 639 | + |
|---|
| 640 | +availablePkgs :: PackageName -> IO [(PackageId, [Dependency])] |
|---|
| 641 | +availablePkgs p = mapM perPkgId =<< availablePkgIds p |
|---|
| 642 | + where perPkgId pkgId = do |
|---|
| 643 | + genDesc <- loadPackageDescription pkgId |
|---|
| 644 | + let desc = flattenPackageDescription genDesc |
|---|
| 645 | + deps = buildDepends desc |
|---|
| 646 | + result = pkgId `seq` deps `seq` (pkgId, deps) |
|---|
| 647 | + -- Strict evaluation of PackageId and [Dependency] so that the now |
|---|
| 648 | + -- useless PackageDescription is no longer retained. |
|---|
| 649 | + result `seq` return result |
|---|
| 650 | + |
|---|
| 651 | +------------------------------------------------------------------------------- |
|---|
| 652 | + |
|---|
| 653 | +-- |Stores the reverse dependency information of all packages in the database. |
|---|
| 654 | +writeRevDepFiles :: RD.RevDepMap -> RD.RevDepMap -> IO () |
|---|
| 655 | +writeRevDepFiles direct total = mapM_ (uncurry $ writeRevDepFile direct total) |
|---|
| 656 | + $ Mp.assocs total |
|---|
| 657 | + |
|---|
| 658 | +{-| Stores the reverse dependency information of a package in the database. |
|---|
| 659 | + |
|---|
| 660 | +The first line in the file contains information about the package itself. The |
|---|
| 661 | +following lines pertain to its reverse dependencies. |
|---|
| 662 | + |
|---|
| 663 | +Each line consists of 4 fields, separated by ',': |
|---|
| 664 | + |
|---|
| 665 | +1. The PackageIdentifier |
|---|
| 666 | +2. Number of direct reverse dependencies |
|---|
| 667 | +3. Number of indirect reverse dependencies (total - direct) |
|---|
| 668 | +4. Flag indicating whether this package is a direct reverse dependency or an |
|---|
| 669 | + indirect one ('D' or 'I'). |
|---|
| 670 | +-} |
|---|
| 671 | +writeRevDepFile :: RD.RevDepMap -> RD.RevDepMap -> PackageId -> S.Set PackageId -> IO () |
|---|
| 672 | +writeRevDepFile direct total pkgId totalRevDeps = |
|---|
| 673 | + writeFile (localFile $ revDepsFile pkgId) fileContents |
|---|
| 674 | + where |
|---|
| 675 | + directDeps :: S.Set PackageId |
|---|
| 676 | + directDeps = RD.lookup direct pkgId |
|---|
| 677 | + |
|---|
| 678 | + fileContents :: String |
|---|
| 679 | + fileContents = unlines |
|---|
| 680 | + . map (\dep -> let numDirect = S.size $ RD.lookup direct dep |
|---|
| 681 | + numTotal = S.size $ RD.lookup total dep |
|---|
| 682 | + numIndirect = numTotal - numDirect |
|---|
| 683 | + in intercalate "," |
|---|
| 684 | + [ display dep |
|---|
| 685 | + , show numDirect |
|---|
| 686 | + , show numIndirect |
|---|
| 687 | + , if S.member dep directDeps |
|---|
| 688 | + then "D" -- (D)irect |
|---|
| 689 | + else "I" -- (I)ndirect |
|---|
| 690 | + ] |
|---|
| 691 | + ) |
|---|
| 692 | + $ pkgId : S.toAscList totalRevDeps |
|---|
| 693 | addfile ./revdeps.hs |
|---|
| 694 | hunk ./revdeps.hs 1 |
|---|
| 695 | +-- CGI program listing package reverse dependencies |
|---|
| 696 | +module Main (main) where |
|---|
| 697 | + |
|---|
| 698 | +import Distribution.Package ( PackageIdentifier(..) ) |
|---|
| 699 | +import Distribution.Version ( Version(..) ) |
|---|
| 700 | +import Distribution.Text ( display ) |
|---|
| 701 | +import HackagePage ( hackagePage ) |
|---|
| 702 | +import Locations ( pkgListURL ) |
|---|
| 703 | +import Network.CGI ( CGI, CGIResult, runCGI, handleErrors |
|---|
| 704 | + , liftIO, output, outputNotFound |
|---|
| 705 | + , pathInfo, redirect |
|---|
| 706 | + ) |
|---|
| 707 | +import PublicFile ( localFile ) |
|---|
| 708 | +import RevDepsPage ( getPkgRevDepsBody ) |
|---|
| 709 | +import System.Directory ( doesFileExist ) |
|---|
| 710 | +import Text.XHtml ( renderHtml ) |
|---|
| 711 | +import Util ( splitOn, availableVersions |
|---|
| 712 | + , cabalFile, maybeLast |
|---|
| 713 | + , readPackageId, revDepsURL |
|---|
| 714 | + ) |
|---|
| 715 | + |
|---|
| 716 | +main :: IO () |
|---|
| 717 | +main = runCGI . handleErrors $ do |
|---|
| 718 | + path <- pathInfo |
|---|
| 719 | + let pathParts = filter (not . null) $ splitOn '/' path |
|---|
| 720 | + case pathParts of |
|---|
| 721 | + [] -> redirect pkgListURL |
|---|
| 722 | + [pname] -> |
|---|
| 723 | + case readPackageId pname of |
|---|
| 724 | + Just pkgId -> showRevDeps pkgId |
|---|
| 725 | + Nothing -> outputNotFound "malformed package identifier" |
|---|
| 726 | + _ -> outputNotFound "malformed URL" |
|---|
| 727 | + |
|---|
| 728 | +showRevDeps :: PackageIdentifier -> CGI CGIResult |
|---|
| 729 | +showRevDeps (PackageIdentifier pname (Version [] [])) = do |
|---|
| 730 | + -- name only: get the most recent version |
|---|
| 731 | + vs <- liftIO (availableVersions pname) |
|---|
| 732 | + case maybeLast vs of |
|---|
| 733 | + Just v -> redirect (revDepsURL (PackageIdentifier pname v)) |
|---|
| 734 | + Nothing -> outputNotFound $ |
|---|
| 735 | + "no such package '" ++ display pname ++ "'" |
|---|
| 736 | +showRevDeps pkgId = do e <- liftIO $ doesFileExist (localFile $ cabalFile pkgId) |
|---|
| 737 | + if e |
|---|
| 738 | + then do page <- liftIO $ getPkgRevDepsBody pkgId |
|---|
| 739 | + output . renderHtml |
|---|
| 740 | + . hackagePage pkgIdStr |
|---|
| 741 | + $ page |
|---|
| 742 | + else outputNotFound ("no such package '" ++ pkgIdStr ++ "'") |
|---|
| 743 | + where pkgIdStr = display pkgId |
|---|
| 744 | + |
|---|
| 745 | } |
|---|
| 746 | |
|---|
| 747 | Context: |
|---|
| 748 | |
|---|
| 749 | [compile with -O |
|---|
| 750 | Ross Paterson <ross@soi.city.ac.uk>**20090824150826 |
|---|
| 751 | Ignore-this: 67ea1327df7bd8df059694d45a16dc0e |
|---|
| 752 | ] |
|---|
| 753 | [tweak locations of distromaps |
|---|
| 754 | Ross Paterson <ross@soi.city.ac.uk>**20090824150257 |
|---|
| 755 | Ignore-this: d642276f3667e3a90065e57005089bd6 |
|---|
| 756 | ] |
|---|
| 757 | [Mention splitDistroMap in README |
|---|
| 758 | Joachim Breitner <mail@joachim-breitner.de>**20090822165007 |
|---|
| 759 | Ignore-this: 4af14467aa9dc0267dde9b6b886de4dc |
|---|
| 760 | ] |
|---|
| 761 | [Avoid compiler warnings in code added by me |
|---|
| 762 | Joachim Breitner <mail@joachim-breitner.de>**20090822164654 |
|---|
| 763 | Ignore-this: c144ce4997793fefc1bcfb006c21abca |
|---|
| 764 | ] |
|---|
| 765 | [Add splitDistroMap to Makefile |
|---|
| 766 | Joachim Breitner <mail@joachim-breitner.de>**20090822164644 |
|---|
| 767 | Ignore-this: 11d7c96d0158487d03285cb6cb6a366 |
|---|
| 768 | ] |
|---|
| 769 | [Use the new per-package DistroInfo API in PackagePage |
|---|
| 770 | Joachim Breitner <mail@joachim-breitner.de>**20090822164057 |
|---|
| 771 | Ignore-this: 918119c885ae61604bbeb7e8806a5642 |
|---|
| 772 | ] |
|---|
| 773 | [Binary program to split the distro map |
|---|
| 774 | Joachim Breitner <mail@joachim-breitner.de>**20090822163821 |
|---|
| 775 | Ignore-this: 6c0d2733d78e772582f8a8f142ebbee4 |
|---|
| 776 | ] |
|---|
| 777 | [DistroInfo.splitDistroInfo |
|---|
| 778 | Joachim Breitner <mail@joachim-breitner.de>**20090822163712 |
|---|
| 779 | Ignore-this: 7340701ff507210abfe06cb3048d4935 |
|---|
| 780 | |
|---|
| 781 | Add a function to DistroInfo to split the all-archive-distro-maps per package, |
|---|
| 782 | and write out short files per PackageName (not package+version) with only the |
|---|
| 783 | information for that package, to reduce parsing time. |
|---|
| 784 | ] |
|---|
| 785 | [New function Util.unversionedPackageDir |
|---|
| 786 | Joachim Breitner <mail@joachim-breitner.de>**20090822163609 |
|---|
| 787 | Ignore-this: bf246d5c43642614884da3a26bbd001f |
|---|
| 788 | |
|---|
| 789 | This is like packageDir, but takes a PackageName instead of a PackageIdentifier |
|---|
| 790 | and thus returns the parent directory of packageDir. This new function is then |
|---|
| 791 | also used in packageDir. |
|---|
| 792 | ] |
|---|
| 793 | [Implement DistroInfo |
|---|
| 794 | Joachim Breitner <mail@joachim-breitner.de>**20090726132613 |
|---|
| 795 | Ignore-this: 1e2fee85bbad474dc2eef2377e50a1e1 |
|---|
| 796 | ] |
|---|
| 797 | [Add a note in the README about the files |
|---|
| 798 | Joachim Breitner <mail@joachim-breitner.de>**20090726131937 |
|---|
| 799 | Ignore-this: 7d581e418b9c82a24d1367946ac81f50 |
|---|
| 800 | ] |
|---|
| 801 | [Set up DistroInfo module |
|---|
| 802 | Joachim Breitner <mail@joachim-breitner.de>**20090726113015 |
|---|
| 803 | Ignore-this: 4c4e6a6fe6fa5a9044363097b5005159 |
|---|
| 804 | ] |
|---|
| 805 | [fix haddock lexer (fixes #569) |
|---|
| 806 | Ross Paterson <ross@soi.city.ac.uk>**20090801141552 |
|---|
| 807 | Ignore-this: 561b885aea712bf59fedac5e0928740a |
|---|
| 808 | ] |
|---|
| 809 | [show source repository |
|---|
| 810 | Ross Paterson <ross@soi.city.ac.uk>**20090706170551 |
|---|
| 811 | Ignore-this: 234c01bf707eaec9ac4efc8ca33ae7e6 |
|---|
| 812 | |
|---|
| 813 | Only shows the development repo, and may be a bit simplistic. |
|---|
| 814 | ] |
|---|
| 815 | [shorter package URL |
|---|
| 816 | Ross Paterson <ross@soi.city.ac.uk>**20090611154034 |
|---|
| 817 | Ignore-this: c812b49a1ca575e9c952d768860f3e2a |
|---|
| 818 | ] |
|---|
| 819 | [canonicalize category links |
|---|
| 820 | Ross Paterson <ross@soi.city.ac.uk>**20090611154013 |
|---|
| 821 | Ignore-this: 4b320ba32d1aee8b92ca9c96e76bf112 |
|---|
| 822 | ] |
|---|
| 823 | [use display instead of show on license field |
|---|
| 824 | Ross Paterson <ross@soi.city.ac.uk>**20090119134457] |
|---|
| 825 | [handle WildcardVersion |
|---|
| 826 | Ross Paterson <ross@soi.city.ac.uk>**20081225024413] |
|---|
| 827 | [explicit imports to avoid clash with Cabal-1.7 |
|---|
| 828 | Ross Paterson <ross@soi.city.ac.uk>**20081222124657] |
|---|
| 829 | [add bug tracker link (#415) |
|---|
| 830 | Ross Paterson <ross@soi.city.ac.uk>**20081126232839] |
|---|
| 831 | [non-semantic changes to sync lexer and parser with versions in GHC |
|---|
| 832 | Ross Paterson <ross@soi.city.ac.uk>**20081115170018] |
|---|
| 833 | [update Haddock parser to 0.9 (fixes #406) |
|---|
| 834 | Ross Paterson <ross@soi.city.ac.uk>**20081114235827] |
|---|
| 835 | [record times in UTC |
|---|
| 836 | Ross Paterson <ross@soi.city.ac.uk>**20081109151646] |
|---|
| 837 | [show build failures and sucesses on different versions of GHC |
|---|
| 838 | Ross Paterson <ross@soi.city.ac.uk>**20081109135425] |
|---|
| 839 | [Read the .cabal file as UTF8 when unpacking (from Duncan Coutts) |
|---|
| 840 | Ross Paterson <ross@soi.city.ac.uk>**20081101154633 |
|---|
| 841 | Previously the upload check preview displayed incorrect encoding of |
|---|
| 842 | people's names and did not validate incorrect UTF8 encodings. |
|---|
| 843 | ] |
|---|
| 844 | [use sparklines generated on an upload |
|---|
| 845 | Ross Paterson <ross@soi.city.ac.uk>**20081024122101] |
|---|
| 846 | [add graph to Recent additions page |
|---|
| 847 | Ross Paterson <ross@soi.city.ac.uk>**20081024001245] |
|---|
| 848 | [uniform layout whether or not haddock present, with italics for non-module nodes |
|---|
| 849 | Ross Paterson <ross@soi.city.ac.uk>**20081014100238] |
|---|
| 850 | [reformat the module list to look a bit more like Haddock's |
|---|
| 851 | Ross Paterson <ross@soi.city.ac.uk>**20081014083632] |
|---|
| 852 | [Render exposed modules as a nested list (#308) |
|---|
| 853 | Ross Paterson <ross@soi.city.ac.uk>**20081014074946 |
|---|
| 854 | |
|---|
| 855 | Written by Bas van Dijk. |
|---|
| 856 | ] |
|---|
| 857 | [Marking packages deprecated |
|---|
| 858 | Chry Cheng <chrycheng@gmail.com>**20080828145516 |
|---|
| 859 | Fixes ticket no. 261 as discussed in its annotations. Packages with "deprecated" "true" are excluded from the package list. Packages with "superseded by" tags provide links to their superseding packages in the package page. |
|---|
| 860 | ] |
|---|
| 861 | [Update deps to require Cabal-1.6 |
|---|
| 862 | Duncan Coutts <duncan@haskell.org>**20081011002506] |
|---|
| 863 | [Update install procedure to install the preferred-versions |
|---|
| 864 | Duncan Coutts <duncan@haskell.org>**20081010000322] |
|---|
| 865 | [Add the initial preferred-versions list |
|---|
| 866 | Duncan Coutts <duncan@haskell.org>**20081010000306] |
|---|
| 867 | [Add the preferred-versions file into the 00-index.tar.gz file |
|---|
| 868 | Duncan Coutts <duncan@haskell.org>**20081009235419 |
|---|
| 869 | Old clients should ignore it. |
|---|
| 870 | ] |
|---|
| 871 | [update files using mv to avoid corruption |
|---|
| 872 | Ross Paterson <ross@soi.city.ac.uk>**20080907114910] |
|---|
| 873 | [put synopsis in header, show version in context |
|---|
| 874 | Ross Paterson <ross@soi.city.ac.uk>**20080905162925] |
|---|
| 875 | [fix warning |
|---|
| 876 | Ross Paterson <ross@soi.city.ac.uk>**20080905162858] |
|---|
| 877 | [eliminate redundant dependencies |
|---|
| 878 | Ross Paterson <ross@soi.city.ac.uk>**20080902001615] |
|---|
| 879 | [update for Cabal 1.5 |
|---|
| 880 | Ross Paterson <ross@soi.city.ac.uk>**20080827020703] |
|---|
| 881 | [use "none" for unmaintained packages |
|---|
| 882 | Ross Paterson <ross@soi.city.ac.uk>**20080723224421] |
|---|
| 883 | [add Hayoo to menu bar |
|---|
| 884 | Ross Paterson <ross@soi.city.ac.uk>**20080723214433] |
|---|
| 885 | [use a single methods to get the package info for display |
|---|
| 886 | Ross Paterson <ross@soi.city.ac.uk>**20080628231737] |
|---|
| 887 | [don't build index asynchronously |
|---|
| 888 | Ross Paterson <ross@soi.city.ac.uk>**20080628231704] |
|---|
| 889 | [flag null maintainer field on package page |
|---|
| 890 | Ross Paterson <ross@soi.city.ac.uk>**20080628231424] |
|---|
| 891 | [use non-versioned links in the package index (#271, #278) |
|---|
| 892 | Ross Paterson <ross@soi.city.ac.uk>**20080510234607] |
|---|
| 893 | [if a package has built, ignore any failures |
|---|
| 894 | Ross Paterson <ross@soi.city.ac.uk>**20080425154935] |
|---|
| 895 | [track changes to checkPackage |
|---|
| 896 | Ross Paterson <ross@soi.city.ac.uk>**20080424003335] |
|---|
| 897 | [add a meta tag declaring the charset as ISO-8859-1, as that's what Text.XHtml generates |
|---|
| 898 | Ross Paterson <ross@soi.city.ac.uk>**20080328154601] |
|---|
| 899 | [make parse warnings fatal |
|---|
| 900 | Ross Paterson <ross@soi.city.ac.uk>**20080328121040] |
|---|
| 901 | [update to Cabal 1.3.9 |
|---|
| 902 | Ross Paterson <ross@soi.city.ac.uk>**20080328120711] |
|---|
| 903 | [disallow updating an existing package |
|---|
| 904 | Ross Paterson <ross@soi.city.ac.uk>**20080328120600] |
|---|
| 905 | [generate 00-index.tar.gz asynchronously |
|---|
| 906 | Ross Paterson <ross@soi.city.ac.uk>**20080302105639] |
|---|
| 907 | [prune the search for cabal files to make it go faster |
|---|
| 908 | Ross Paterson <ross@soi.city.ac.uk>**20080302105432] |
|---|
| 909 | [add small latest-versions lister |
|---|
| 910 | Ross Paterson <ross@soi.city.ac.uk>**20080221134229] |
|---|
| 911 | [use absolute filenames when looking for packages |
|---|
| 912 | Ross Paterson <ross@soi.city.ac.uk>**20080221124040] |
|---|
| 913 | [longer label on the search button |
|---|
| 914 | Ross Paterson <ross@soi.city.ac.uk>**20080221123956] |
|---|
| 915 | [simple implementation of tags, starting with upload info |
|---|
| 916 | Ross Paterson <ross@soi.city.ac.uk>**20080216021131] |
|---|
| 917 | [swap arguments to extraChecks |
|---|
| 918 | Ross Paterson <ross@soi.city.ac.uk>**20080214182808] |
|---|
| 919 | [fix warning |
|---|
| 920 | Ross Paterson <ross@soi.city.ac.uk>**20080214182753] |
|---|
| 921 | [Update to latest Cabal lib API and use new package checking code |
|---|
| 922 | Duncan Coutts <duncan@haskell.org>**20080213201347 |
|---|
| 923 | Compiles but otherwise totally untested. |
|---|
| 924 | ] |
|---|
| 925 | [remove private copies of functions now in ghc 6.8 |
|---|
| 926 | Ross Paterson <ross@soi.city.ac.uk>**20080212011430] |
|---|
| 927 | [introduce PublicFile for files visible through the web |
|---|
| 928 | Ross Paterson <ross@soi.city.ac.uk>**20080212005643] |
|---|
| 929 | [refactoring of upload and check scripts |
|---|
| 930 | Ross Paterson <ross@soi.city.ac.uk>**20080211131109] |
|---|
| 931 | [unpack the whole directory, not just the .cabal file |
|---|
| 932 | Ross Paterson <ross@soi.city.ac.uk>**20080211131009] |
|---|
| 933 | [add a Google search box to the package list page |
|---|
| 934 | Ross Paterson <ross@soi.city.ac.uk>**20080203021954] |
|---|
| 935 | [swap depends-on and required-by maps |
|---|
| 936 | Ross Paterson <ross@soi.city.ac.uk>**20080202012507] |
|---|
| 937 | [list successful and unsuccessful builds, with logs |
|---|
| 938 | Ross Paterson <ross@soi.city.ac.uk>**20080126013443] |
|---|
| 939 | [blacklist Application, Tool and Type categories |
|---|
| 940 | Ross Paterson <ross@soi.city.ac.uk>**20071213074800] |
|---|
| 941 | [add author |
|---|
| 942 | Ross Paterson <ross@soi.city.ac.uk>**20071213074632] |
|---|
| 943 | [correct and simplify the library and programs test |
|---|
| 944 | Ross Paterson <ross@soi.city.ac.uk>**20071210104009] |
|---|
| 945 | [capitalize category names |
|---|
| 946 | Ross Paterson <ross@soi.city.ac.uk>**20071130143321] |
|---|
| 947 | [merge category names that differ only in case |
|---|
| 948 | Ross Paterson <ross@soi.city.ac.uk>**20071130142342] |
|---|
| 949 | [render equality constraints concisely |
|---|
| 950 | Ross Paterson <ross@soi.city.ac.uk>**20071128005652] |
|---|
| 951 | [ignore case when sorting lists of dependent packages |
|---|
| 952 | Ross Paterson <ross@soi.city.ac.uk>**20071120123549] |
|---|
| 953 | [display dependencies in disjunctive normal form |
|---|
| 954 | Ross Paterson <ross@soi.city.ac.uk>**20071024225216] |
|---|
| 955 | [Oops, need the flattened package description to get exposed modules and executables |
|---|
| 956 | Ross Paterson <ross@soi.city.ac.uk>**20071024070848] |
|---|
| 957 | [use GenericPackageDescription instead of PackageDescription |
|---|
| 958 | Ross Paterson <ross@soi.city.ac.uk>**20071024064933] |
|---|
| 959 | [now need Cabal >= 1.2.1 |
|---|
| 960 | Ross Paterson <ross@soi.city.ac.uk>**20071021155643] |
|---|
| 961 | [update for Cabal 1.2.1 |
|---|
| 962 | Ross Paterson <ross@soi.city.ac.uk>**20071021155322] |
|---|
| 963 | [cabal packaging (based on work of Trevor Elliott) |
|---|
| 964 | Ross Paterson <ross@soi.city.ac.uk>**20071019124210] |
|---|
| 965 | [also install search |
|---|
| 966 | Ross Paterson <ross@soi.city.ac.uk>**20070909185526] |
|---|
| 967 | [Added search functionality (by Sascha Böhme), but not yet in main menu |
|---|
| 968 | Ross Paterson <ross@soi.city.ac.uk>**20070909140603] |
|---|
| 969 | [update for Cabal-1.2 |
|---|
| 970 | Ross Paterson <ross@soi.city.ac.uk>**20070907234506] |
|---|
| 971 | [ensure the package list contains latest versions, plus some refacting |
|---|
| 972 | Ross Paterson <ross@soi.city.ac.uk>**20070723204248] |
|---|
| 973 | [add link to build log to package page |
|---|
| 974 | Ross Paterson <ross@soi.city.ac.uk>**20070720124702] |
|---|
| 975 | [minor build updates |
|---|
| 976 | Ross Paterson <ross@soi.city.ac.uk>**20070617213315] |
|---|
| 977 | [fix rendering of identifiers |
|---|
| 978 | Ross Paterson <ross@soi.city.ac.uk>**20070617213249] |
|---|
| 979 | [add missing file |
|---|
| 980 | Ross Paterson <ross@soi.city.ac.uk>**20070530140019] |
|---|
| 981 | [bugfix for previous commit |
|---|
| 982 | Ross Paterson <ross@soi.city.ac.uk>**20070510142803] |
|---|
| 983 | [fix error in building index |
|---|
| 984 | Ross Paterson <ross@soi.city.ac.uk>**20070508165611] |
|---|
| 985 | [include a package in the list only if it has a Cabal file |
|---|
| 986 | Ross Paterson <ross@soi.city.ac.uk>**20070506180938] |
|---|
| 987 | [change the directory layout of the HackageDB data |
|---|
| 988 | Ross Paterson <ross@soi.city.ac.uk>**20070506151844 |
|---|
| 989 | |
|---|
| 990 | Put version in a separate directory (to simplify future expansion). |
|---|
| 991 | This will not affect users of the web interface, but will be a breaking |
|---|
| 992 | change for those who reference the files directly, notably cabal-install. |
|---|
| 993 | |
|---|
| 994 | Here's how the positions of the files of the binary package change |
|---|
| 995 | (-> denotes a symbolic link): |
|---|
| 996 | |
|---|
| 997 | Old layout New layout |
|---|
| 998 | -------------------------------------------------------------------- |
|---|
| 999 | binary/binary-0.2.cabal binary/0.2/binary.cabal |
|---|
| 1000 | binary/binary-0.2.tar.gz binary/0.2/binary-0.2.tar.gz |
|---|
| 1001 | binary/binary-0.2.misc/doc/html/ binary/0.2/doc/html/ |
|---|
| 1002 | binary/binary-0.3.cabal binary/0.3/binary.cabal |
|---|
| 1003 | binary/binary-0.3.tar.gz binary/0.3/binary-0.3.tar.gz |
|---|
| 1004 | binary/binary-0.3.misc/doc/html/ binary/0.3/doc/html/ |
|---|
| 1005 | binary/latest.misc -> binary-0.3.misc binary/latest -> 0.3 |
|---|
| 1006 | ] |
|---|
| 1007 | [catch "Unclassified" category |
|---|
| 1008 | Ross Paterson <ross@soi.city.ac.uk>**20070307011355] |
|---|
| 1009 | [use local copy of Cabal logo |
|---|
| 1010 | Ross Paterson <ross@soi.city.ac.uk>**20070225125801] |
|---|
| 1011 | [make "recent additions" a generated page instead of a CGI script |
|---|
| 1012 | Ross Paterson <ross@soi.city.ac.uk>**20070220235702] |
|---|
| 1013 | [tweaks to package list |
|---|
| 1014 | Ross Paterson <ross@soi.city.ac.uk>**20070220235601] |
|---|
| 1015 | [generate RSS feed of recent updates |
|---|
| 1016 | Ross Paterson <ross@soi.city.ac.uk>**20070214185538] |
|---|
| 1017 | [bug fix: show preview even if no warnings |
|---|
| 1018 | Ross Paterson <ross@soi.city.ac.uk>**20070213180708] |
|---|
| 1019 | [check-pkg also returns plain text if requested |
|---|
| 1020 | Ross Paterson <ross@soi.city.ac.uk>**20070213001039] |
|---|
| 1021 | [for plain text clients, return only the warnings |
|---|
| 1022 | Ross Paterson <ross@soi.city.ac.uk>**20070211171633] |
|---|
| 1023 | [use CGI type synonym |
|---|
| 1024 | Ross Paterson <ross@soi.city.ac.uk>**20070210152353] |
|---|
| 1025 | [refactor pkgBody arguments as a record |
|---|
| 1026 | Ross Paterson <ross@soi.city.ac.uk>**20070208194243] |
|---|
| 1027 | [strip executables |
|---|
| 1028 | Ross Paterson <ross@soi.city.ac.uk>**20070207233429] |
|---|
| 1029 | [mark property table |
|---|
| 1030 | Ross Paterson <ross@soi.city.ac.uk>**20070207233402] |
|---|
| 1031 | [point to accounts page |
|---|
| 1032 | Ross Paterson <ross@soi.city.ac.uk>**20070207230638] |
|---|
| 1033 | [install upload-pkg in the correct place |
|---|
| 1034 | Ross Paterson <ross@soi.city.ac.uk>**20070206001525] |
|---|
| 1035 | [new location <pkgid>.misc/doc for docs |
|---|
| 1036 | Ross Paterson <ross@soi.city.ac.uk>**20070205004623] |
|---|
| 1037 | [versioned haddock documentation |
|---|
| 1038 | Ross Paterson <ross@soi.city.ac.uk>**20070203202526] |
|---|
| 1039 | [if PACKAGE/doc/html exists, module names are links into it |
|---|
| 1040 | Ross Paterson <ross@soi.city.ac.uk>**20070203170215 |
|---|
| 1041 | (Generation of haddock documentation is not yet automated, though) |
|---|
| 1042 | ] |
|---|
| 1043 | [minor refactoring |
|---|
| 1044 | Ross Paterson <ross@soi.city.ac.uk>**20070202121300] |
|---|
| 1045 | [change package links from pkg/vers to pkg-vers |
|---|
| 1046 | Ross Paterson <ross@soi.city.ac.uk>**20070201143905] |
|---|
| 1047 | [package-ids are unambiguous |
|---|
| 1048 | Ross Paterson <ross@soi.city.ac.uk>**20070201132112] |
|---|
| 1049 | [allow version tags (they seem harmless) |
|---|
| 1050 | Ross Paterson <ross@soi.city.ac.uk>**20070201131251] |
|---|
| 1051 | [trim long synopses in package list |
|---|
| 1052 | Ross Paterson <ross@soi.city.ac.uk>**20070201100052] |
|---|
| 1053 | [tag category list |
|---|
| 1054 | Ross Paterson <ross@soi.city.ac.uk>**20070131121652] |
|---|
| 1055 | [some re-arrangement |
|---|
| 1056 | Ross Paterson <ross@soi.city.ac.uk>**20070131003654] |
|---|
| 1057 | [add category index to package list |
|---|
| 1058 | Ross Paterson <ross@soi.city.ac.uk>**20070130180021] |
|---|
| 1059 | [tweak Cabal logo |
|---|
| 1060 | Ross Paterson <ross@soi.city.ac.uk>**20070129130941] |
|---|
| 1061 | [add Cabal branding to package page |
|---|
| 1062 | Ross Paterson <ross@soi.city.ac.uk>**20070129122133] |
|---|
| 1063 | [mark package lists with an element class |
|---|
| 1064 | Ross Paterson <ross@soi.city.ac.uk>**20070129092724] |
|---|
| 1065 | [revert to textual indication of package type |
|---|
| 1066 | Ross Paterson <ross@soi.city.ac.uk>**20070129080416] |
|---|
| 1067 | [cleanup |
|---|
| 1068 | Ross Paterson <ross@soi.city.ac.uk>**20070129025127] |
|---|
| 1069 | [more compact presentation of package list |
|---|
| 1070 | Ross Paterson <ross@soi.city.ac.uk>**20070129021339] |
|---|
| 1071 | [show other versions on package page |
|---|
| 1072 | Ross Paterson <ross@soi.city.ac.uk>**20070129020229] |
|---|
| 1073 | [move cabalFile to Util |
|---|
| 1074 | Ross Paterson <ross@soi.city.ac.uk>**20070129014325] |
|---|
| 1075 | [pkg-list: only read the most recent Cabal file for each package |
|---|
| 1076 | Ross Paterson <ross@soi.city.ac.uk>**20070129012719] |
|---|
| 1077 | [trim unused functions |
|---|
| 1078 | Ross Paterson <ross@soi.city.ac.uk>**20070129012355] |
|---|
| 1079 | [add export lists for Main modules |
|---|
| 1080 | Ross Paterson <ross@soi.city.ac.uk>**20070129012315] |
|---|
| 1081 | [fix dependency |
|---|
| 1082 | Ross Paterson <ross@soi.city.ac.uk>**20070129005924] |
|---|
| 1083 | [refactoring of version search |
|---|
| 1084 | Ross Paterson <ross@soi.city.ac.uk>**20070129005845] |
|---|
| 1085 | [switch to Text.XHtml |
|---|
| 1086 | Ross Paterson <ross@soi.city.ac.uk>**20070129001802] |
|---|
| 1087 | [more graceful error on missing package |
|---|
| 1088 | Ross Paterson <ross@soi.city.ac.uk>**20070127171227] |
|---|
| 1089 | [minor simplification |
|---|
| 1090 | Ross Paterson <ross@soi.city.ac.uk>**20070127164406] |
|---|
| 1091 | [minor refactoring |
|---|
| 1092 | Ross Paterson <ross@soi.city.ac.uk>**20070127143750] |
|---|
| 1093 | [shuffle stuff between modules |
|---|
| 1094 | Ross Paterson <ross@soi.city.ac.uk>**20070127142603] |
|---|
| 1095 | [change install to scp + mv |
|---|
| 1096 | Ross Paterson <ross@soi.city.ac.uk>**20070127131030] |
|---|
| 1097 | [reword check output |
|---|
| 1098 | Ross Paterson <ross@soi.city.ac.uk>**20070127130746] |
|---|
| 1099 | [add upload.html |
|---|
| 1100 | Ross Paterson <ross@soi.city.ac.uk>**20070126210510] |
|---|
| 1101 | [re-order things on package page |
|---|
| 1102 | Ross Paterson <ross@soi.city.ac.uk>**20070126204017] |
|---|
| 1103 | [minor refactoring |
|---|
| 1104 | Ross Paterson <ross@soi.city.ac.uk>**20070126202141] |
|---|
| 1105 | [tabulate fields |
|---|
| 1106 | Ross Paterson <ross@soi.city.ac.uk>**20070126201050] |
|---|
| 1107 | [remove superfluous thehtml |
|---|
| 1108 | Ross Paterson <ross@soi.city.ac.uk>**20070126174820] |
|---|
| 1109 | [ensure that showPackageId produces the original pkg-id |
|---|
| 1110 | Ross Paterson <ross@soi.city.ac.uk>**20070126150901 |
|---|
| 1111 | |
|---|
| 1112 | Rule out version numbers like "1.00" -> [1,0] -> "1.0". These ought to be |
|---|
| 1113 | rejected by the parser. |
|---|
| 1114 | ] |
|---|
| 1115 | [add boilerplate header to each page |
|---|
| 1116 | Ross Paterson <ross@soi.city.ac.uk>**20070126143901] |
|---|
| 1117 | [remove old form-based parameters to package script |
|---|
| 1118 | Ross Paterson <ross@soi.city.ac.uk>**20070126115030] |
|---|
| 1119 | [tweak category headings |
|---|
| 1120 | Ross Paterson <ross@soi.city.ac.uk>**20070126112054] |
|---|
| 1121 | [make package URLs a bit shorter |
|---|
| 1122 | Ross Paterson <ross@soi.city.ac.uk>**20070125105147 |
|---|
| 1123 | |
|---|
| 1124 | * remove .cgi from CGI scripts in cgi-bin |
|---|
| 1125 | |
|---|
| 1126 | * use PATHINFO instead of form data to identify packages. |
|---|
| 1127 | |
|---|
| 1128 | So now its .../package/<pkg>/<version> or just .../package/<pkg> |
|---|
| 1129 | ] |
|---|
| 1130 | [some refactoring |
|---|
| 1131 | Ross Paterson <ross@soi.city.ac.uk>**20070118102430] |
|---|
| 1132 | [append a preview of the package page to the check-pkg output |
|---|
| 1133 | Ross Paterson <ross@soi.city.ac.uk>**20070118003003] |
|---|
| 1134 | [add a README file with overview and install instructions |
|---|
| 1135 | Ross Paterson <ross@soi.city.ac.uk>**20070116153445] |
|---|
| 1136 | [clean up locations a bit |
|---|
| 1137 | Ross Paterson <ross@soi.city.ac.uk>**20070116123020] |
|---|
| 1138 | [parse and markup package descriptions with code stolen from Haddock |
|---|
| 1139 | Ross Paterson <ross@soi.city.ac.uk>**20070116105520] |
|---|
| 1140 | [temporarily downgrade repeated-upload check to a warning |
|---|
| 1141 | Ross Paterson <ross@soi.city.ac.uk>**20070116073009 |
|---|
| 1142 | |
|---|
| 1143 | The check seems like a good idea in the longer term, but |
|---|
| 1144 | It's a bit cumbersome while we're all still experimenting. |
|---|
| 1145 | ] |
|---|
| 1146 | [more compact log lines |
|---|
| 1147 | Ross Paterson <ross@soi.city.ac.uk>**20070113010328] |
|---|
| 1148 | [fix previous commit |
|---|
| 1149 | Ross Paterson <ross@soi.city.ac.uk>**20070112155632] |
|---|
| 1150 | [use errorOutput for error cases |
|---|
| 1151 | Ross Paterson <ross@soi.city.ac.uk>**20070112151251] |
|---|
| 1152 | [basename: strip to slash or backslash (which IE includes in filenames) |
|---|
| 1153 | Ross Paterson <ross@soi.city.ac.uk>**20070112143846] |
|---|
| 1154 | [use a different tmp directory for each process |
|---|
| 1155 | Ross Paterson <ross@soi.city.ac.uk>**20070111010943] |
|---|
| 1156 | [don't accept "Foreign binding" as a category |
|---|
| 1157 | Ross Paterson <ross@soi.city.ac.uk>**20070110233221] |
|---|
| 1158 | [fix stylesheet location |
|---|
| 1159 | Ross Paterson <ross@soi.city.ac.uk>**20070110182307] |
|---|
| 1160 | [change locations to match install on hackage.haskell.org |
|---|
| 1161 | Ross Paterson <ross@soi.city.ac.uk>**20070110170036] |
|---|
| 1162 | [repair post-upload-hook |
|---|
| 1163 | Ross Paterson <ross@soi.city.ac.uk>**20070109224215] |
|---|
| 1164 | [fallback for category: top-level of module hierarchy |
|---|
| 1165 | Ross Paterson <ross@soi.city.ac.uk>**20070109224115] |
|---|
| 1166 | [initial import |
|---|
| 1167 | Ross Paterson <ross@soi.city.ac.uk>**20070109004703 |
|---|
| 1168 | |
|---|
| 1169 | This is a crude first cut at an interface to the Hackage package database: |
|---|
| 1170 | * generating a package list (pkg-list) |
|---|
| 1171 | * page describing a package (package.cgi) |
|---|
| 1172 | * apply basic checks to a Cabal package (check-pkg.cgi) |
|---|
| 1173 | * upload a Cabal package to the database (upload-pkg.cgi) |
|---|
| 1174 | ] |
|---|
| 1175 | Patch bundle hash: |
|---|
| 1176 | f05a1fe98f4435a882637311727ab5bf0759f891 |
|---|