[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: hgettext not migrating without reason.



On Thu, 14 Aug 2014 22:50:00 +0200
Joachim Breitner <nomeata@debian.org> wrote:

> the information in the PTS on package uninstallability is unfortunately
> not very helpful.
> 
> What I do to investigate such problems is
>  * make sure all Haskell packages are installable:
> http://jenkins.debian.net/job/chroot-installation_sid_install_haskell/
> Last build mentions criterion and notmuch-web, I believe I have fixed
> these yesterday and hope that the job finally succeeds (after 3 months!)
> next time. But this only tests amd64.
>  * make sure that there are no failed builds. Follow the link from
> http://wiki.debian.org/Haskell to see the status of all packages on
> buildd.debian.org, and watch for Failed (icon ~).
>  * check if the binNMU scheduling script wants to schedule more
> packages. Unfortunately, this requires access to wuiet.debian.org.
> Currently, it does not detect problems.
>  * finally, try to make sense of
> https://release.debian.org/britney/update_output.txt
> Look for lines starting with "Trying easy from autohinter" that mention
> haskell packages. A few lines down are lines starting with " * <some
> arch>", these are packages broken by the proposed upgrade (but without
> explanation). The current autohint including gettext seems to break a
> lot of packages, no idea what is left to do.
> 
> 
> Maybe Niels Thyker, who has worked on the autohinter, is interested in
> helping you solve the problem of „why does gettext not migrate“ and
> might want to improve these tools.

Niels Thykier explained a little bit of "why does gettext not migrate",
but more importantly: He told me how to interpret the autohinter
output, in conjunction with the excuses. As it turns out, they seem to
be helpful after all.

After thinking about this, I made a tool that takes a packages and
shows all (at least I hope it gets all of them) the useful reasons why
it can't migrate.

It does this as follows:
 -Look in the britney output for the autohint that contains the
  requested package.
 -Get all the packages it breaks.
 -Gather all excuses for that broken packages.
 -Throw all excuses away, except those that are identified as
  interesting.

This gives a list of excuses that isn't as overwhelming as the
autohinter output.

The following excuses are identified as interesting:
 -out of date on...
 -introduces new bugs
 -Too young (It's not really interesting, but it helps to tell if
  there's a bug in the program or if you just have to wait until the
  transition can happen)

The following excuses are discarded on purpose:
 -Depends: (because the dependency should be listed seperately.)

If you find some excuses that should be also marked as interesting,
please contact me.

I didn't come up with a name yet. So I'm interested in your
suggestions. (And it's really tedious to call it "The tool that tells
you why your packages don't migrate".)

I'm not sure wether to put it into the tools repository or to the
package-plan. I more tend to put it to the tools, but please tell me
what you're thinking.

The source code is attached. The program takes very long to produce
it's result, since it needs to do a lot of calls to apt-cache and
grep-excuses.
It uses the local cache to map binary packages to src packages. So it
might fail on testing, if there is a broken package, which is not in
testing.

Regards
Sven
import Text.Regex.PCRE
import System.Environment
import System.Exit
import System.Process
import Data.Maybe
import Data.List
import Data.Char
import qualified Data.Set as S
import Control.Exception
import Debug.Trace

data Excuses = Excuses String [String]

isEmpty :: Excuses -> Bool
isEmpty (Excuses _ []) = False
isEmpty (Excuses _ _) = True

excuses2String :: Excuses -> String
excuses2String (Excuses pkg excuses) = unlines $ (pkg ++ ":"):(map ("    " ++) excuses)

main = do
  (britneyout, package) <- getArgs >>= parse
  output <- fmap lines $ readFile britneyout
  let bins = getBinBlockers output package
  result <- try (fmap nub $ mapM getSrcPackage bins) :: IO (Either ErrorCall [String])
  srcBlockers <- case result of
                   Left e -> putStrLn packageNotFoundMsg >> exitFailure
                   Right pkgs -> return pkgs
  excuses <- mapM getExcuse srcBlockers
  let filteredExcuses = filterExcuses excuses
  mapM_ putStrLn $ map excuses2String filteredExcuses

parse :: [String] -> IO (String, String)
parse [britneyout, package] = return (britneyout, package)
parse _ = printUsage >> exitFailure

printUsage :: IO ()
printUsage = do
  progName <- getProgName
  putStrLn $ "Usage: " ++ progName ++ " britney-output package-name"

packageNotFoundMsg :: String
packageNotFoundMsg
    = "Something went wrong.\n\
       \Most likely the package you requested was not processed by the \
       \autohinter."

filterExcuses :: [Excuses] -> [Excuses]
filterExcuses excuses = filter isEmpty $ map filterPkgExcuses excuses
    where filterPkgExcuses (Excuses pkg excuses) = Excuses pkg
                                                   $ filter isInteresting excuses

isInteresting :: String -> Bool
isInteresting excuse = "out of date on" `isPrefixOf` excuse 
                       || "introduces new bugs" `isInfixOf` excuse
                       || "Too young" `isPrefixOf` excuse

getExcuse :: String -> IO Excuses
getExcuse pkg = do
  excuses <- readProcess "/usr/bin/grep-excuses" [pkg] ""
  return $ Excuses pkg $ map (dropWhile isSpace) $ tail $ lines excuses

getSrcPackage :: String -> IO String
getSrcPackage bin = do
  packageDesc <- readProcess "/usr/bin/apt-cache" ["showsrc", bin] ""
  return $ parseDesc packageDesc

parseDesc :: String -> String
parseDesc desc = let ls = lines desc
                     srcln = findSourceLine ls
                 in removeFieldPrefix srcln

findSourceLine :: [String] -> String
findSourceLine (curLine:rest)
    | "Package: " `isPrefixOf` curLine = curLine
    | otherwise = findSourceLine rest

getBinBlockers :: [String] -> String -> [String]
getBinBlockers output package = let arches = getArches package output
                                in nub $ map stripComma
                                       $ concat
                                       $ map words
                                       $ map removeFieldPrefix arches
                                    where stripComma str = if last str == ','
                                                           then init str
                                                           else str

removeFieldPrefix :: String -> String
removeFieldPrefix arch = drop 2 $ dropWhile (/= ':') arch

getArches :: String -> [String] -> [String]
getArches package output = get $ removeStats $ fromJust $ findAutohint package output
    where get (line:rest)
              | line `matches` " *\\* .*:" = line : get rest
              | otherwise = []

removeStats :: [String] -> [String]
removeStats = drop 4

findAutohint :: String -> [String] -> Maybe [String]
findAutohint _ [] = Nothing
findAutohint package (curLine:rest)
    | curLine `matches` ("Trying easy from autohinter.*" ++ package)
        = Just rest
    | otherwise = findAutohint package rest

matches :: String -> String -> Bool
str `matches` pattern = (not . null) (str =~ pattern :: String)

Attachment: signature.asc
Description: PGP signature


Reply to: