[darcs-users] bug report: unrepairable repo

zooko at zooko.com zooko at zooko.com
Thu Oct 7 19:44:51 UTC 2004


I've been pulling darcs patches, and I tried to "fix" a compilation problem
with "find . -name '*darcs_cgi*' -print0 | xargs -0 rm" and 
"find . -name '*Current*' -print0 | xargs -0 rm".

Maybe this wasn't a wise thing to do, but aren't you glad I do unwise things in
order to stress-test darcs?

Anyway, now I get this unrepairable repo.  The full contents of darcs/ are
available at http://zooko.com/darcs.tar.bz2.

Here is a screenlog of me running "darcs check" and "darcs repair" on it:

HACK pion:~/playground/darcs$ darcs check
Looks like we have a difference...
Just {
hunk ./darcs_cgi.lhs 1
-%  Copyright (C) 2002-2004 David Roundy
-%
-%  This program is free software; you can redistribute it and/or modify
-%  it under the terms of the GNU General Public License as published by
-%  the Free Software Foundation; either version 2, or (at your option)
-%  any later version.
-%
-%  This program is distributed in the hope that it will be useful,
-%  but WITHOUT ANY WARRANTY; without even the implied warranty of
-%  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-%  GNU General Public License for more details.
-%
-%  You should have received a copy of the GNU General Public License
-%  along with this program; if not, write to the Free Software Foundation,
-%  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-\chapter{Web interface}
-\label{web_interface}
-
-The \verb!darcs! web interface allows you to conveniently browse the
-information stored in a repository.  You can view the repo by file and see
-the history of that file as various patches were applied, or you can browse
-in patch view mode, seeing which files were modified in each patch.
-
-\begin{code}
-module Main (main) where
-
-import CGI
-import IO
-import Monad ( liftM, liftM2 )
-import FastPackedString
-import List ( sort )
-import Text.Html
-
-import SHA1 ( sha1PS )
-import Patch
-import PatchInfo
-import Repository
-import Directory
-import Autoconf
-import PopulationData
-import Population ( getRepoPopVersion )
-import DarcsUtils
-#include "impossible.h"
-\end{code}
-
-\begin{code}
-main :: IO ()
-main = do
-  my_reposdir <- read_conf "reposdir"
-  setCurrentDirectory my_reposdir
-  wrapper $ cache_page make_page
-\end{code}
-
-\begin{code}
-cache_page :: ([(String,String)] -> IO Html) -> [(String,String)] -> IO Html
-cache_page mp a = do
-  cachedir <- read_conf "cachedir"
-  have_cachedir <- doesDirectoryExist cachedir
-  if not have_cachedir
-   then mp a -- if there's no cachedir, just don't use a cache!  :)
-   else
-    case takeWhile (/='*') query of
-    "" -> mp a
-    rn ->do cached <- (++"/"++qn) `liftM` read_conf "cachedir"
-            repoinv <- (++"/"++rn++"/_darcs/inventory")
-                       `liftM` read_conf "reposdir"
-            is_cached <- doesFileExist cached
-            is_changed <- is_newer repoinv cached
-            if is_cached && not is_changed
-               then do liftM primHtml $ readFile cached
-               else do page <- mp a
-                       writeFile cached (renderHtml page)
-                       return page
-    where query = get_query a
-          qn = sha1PS (packString query)
-is_newer :: FilePath -> FilePath -> IO Bool
-is_newer fa fb = do
-  fa_exists <- doesFileExist fa
-  fb_exists <- doesFileExist fb
-  if fa_exists && fb_exists
-     then liftM2 (>) (getModificationTime fa) (getModificationTime fb)
-     else return False
-\end{code}
-
-The \verb!darcs_cgi! cgi script allows you to browse changes made in your
-darcs repository via the web.  To use it with apache, you can install it
-using \verb!make installserver!, and create a cache directory at
-\verb!/var/cache/darcs!.  This cache directory must be writeable by the
-cgi script, which for me means \verb!chown!ing it to the user and group
-\verb!www-data!.  Finally, you should create a directory named {\tt repos}
-in {\tt /var/www}, in which you will place symlinks to the repos
-themselves.  Once all this is done, the user can then browse the repos at
-{\tt http://your.site/cgi-bin/darcs}.
-
-The repos directory is configurable via the configuration file
-\verb!/etc/darcs/cgi.conf!.  This file can contain comments (any line
-starting with a `\#' char) and key value pairs with an equal sign in
-between.  For example:
-\example{cgi/cgi.conf}
-
-\begin{code}
-read_conf :: String -> IO String
-read_conf var = do
-  ls <- (map (takeWhile (/='#')).lines) `liftM` readFile (darcsconfdir ++ "/cgi.conf")
-        `catchall` return []
-  case filter ((== var).fst) $ map (break (== '=') . filter (/=' ')) ls of
-      [(_,val)] -> return $ tail val
-      _ -> return ""
-\end{code}
-
-\begin{code}
-make_page :: [(String,String)] -> IO Html
-make_page a =
-  case get_query a of
-  "" -> home_page
-  _ -> case get_reponame a of
-       ("Error",msg) -> return $ htmlError $ "Bad URL:\n"++msg
-       (repo,fnpn) -> do
-         setCurrentDirectory repo
-         patches <- read_repo_patches "."
-         case fnpn of
-           "" -> repo_page repo
-           "*" -> patch_page repo
-           _ ->
-            case get_filename_and_patchname fnpn of
-             ["Error",msg] -> return $ htmlError $ "Bad URL:\n"++msg
-             [_,""] ->
-                 return $ htmlError $ "Haven't yet implemented file view."
-             ["",pn] ->
-                 case get_patchinfo_from_name pn patches of
-                 Nothing -> return $ htmlError $ "Patch "++pn++" does not exist."
-                 Just pinfo -> one_patch_page repo pinfo
-             [filename,pn,createdname,cn] ->
-                 case (get_patchinfo_from_name pn patches,
-                       get_patchinfo_from_name cn patches) of
-                 (Just pinfo, Just ci) -> do
-                     mf <- get_markedup_file ci createdname
-                     return $ make_markedup_page repo filename pinfo
-                              createdname ci (map fst patches) mf
-                 _ -> return $ htmlError $
-                      "Patch "++pn++" or maybe "++cn++" does not exist."
-             _ -> impossible
-\end{code}
-
-The page, {\tt http://your.site/cgi-bin/darcs}, displays a listing of all
-repos available on the server.  From this page, the user can get to any
-available repository.
-
-\begin{code}
-home_page :: IO Html
-home_page = do
-  repos <- getDirectoryContents "."
-  return $ header << thetitle << "Darcs repositories:" +++
-         body ! [bgcolor "#ffffff"] <<
-                  (h1 << toHtml "Darcs repositories:")
-                  +++ h3 << (link_repos $ filter (\s->head s /= '.') repos)
-
-link_repos :: [FilePath] -> Html
-link_repos repos = foldl (+++) br $
-                   map (\r-> hotlink ("darcs?"++r++"*") [toHtml r] +++ br) repos
-\end{code}
-
-Clicking on a given repository will take you to the file view page of that
-repository, which shows a listing of all the files in the repo.  This page
-also has a link to the patch view page, which is a bit more interesting.
-
-\begin{code}
-read_repo_patches :: String -> IO [(PatchInfo, Maybe Patch)]
-read_repo_patches d = (reverse . concat) `liftM` read_repo d
-repo_page :: String -> IO Html
-repo_page repo = do
-  patches <- read_repo_patches "."
-  case fst $ head $ reverse $ patches of
-    pinfo -> do
-      pop <- getRepoPopVersion "." pinfo
-      return $ header << thetitle << repotitle repo +++
-             body ! [bgcolor "#ffffff"] <<
-                      (h1 << (toHtml $ repotitle repo) +++
-                       h3 << (hotlink ("darcs?"++repo++"**")
-                              [toHtml "Switch to patch view"]) +++
-                       pop_to_html (repo++"*") pop)
-repotitle :: String -> String
-repotitle repo = "The darcs '"++repo++"' repository"
-\end{code}
-
-In patch view mode, the web interface displays a listing of all the patches
-in the repo.  Clicking on a patch gives a listing of all files that were in
-the repo at the time that patch was applied.
-
-\begin{code}
-patch_page :: String -> IO Html
-patch_page repo = do
-  patches <- read_repo_patches "."
-  return $ header << thetitle << repotitle repo +++
-               body ! [bgcolor "#ffffff"] <<
-                        (h1 << (toHtml $ repotitle repo) +++
-                         h3 << (hotlink ("darcs?"++repo++"*")
-                                [toHtml "Switch to file view"]) +++
-                         (table ! [border 0] <<
-                          (foldl (above) (cell $ h3 << "Patches")
-                           (map (toHtml.(repopatchinfo repo).fst) $ reverse patches))))
-\end{code}
-
-Clicking on one of the files shows the file contents, with added lines
-shown in green, and removed ones in red.  To the left of each line is a
-small `+' and `-'.  These are links to the patch which added or removed
-that line.
-
-\begin{code}
-one_patch_page :: String -> PatchInfo -> IO Html
-one_patch_page repo pinfo = do
-  pop <- getRepoPopVersion "." pinfo
-  return $ header << thetitle << ("Patch:  "++just_name pinfo) +++
-         body ! [bgcolor "#ffffff"] <<
-                  (h3 << (hotlink ("darcs?"++repo++"**")
-                          [toHtml $ "Patch:  "++just_name pinfo]) +++
-                   pop_to_html (repo++"*") pop)
-
-\end{code}
-
-\begin{code}
-make_markedup_page :: String -> FilePath -> PatchInfo
-                   -> FilePath -> PatchInfo -> [PatchInfo]
-                   -> MarkedUpFile -> Html
-make_markedup_page repo f pinfo cfn ci ps mk =
-  header << thetitle << (f++" ** "++just_name pinfo) +++
-    body ! [bgcolor "#ffffff"] <<
-             (nav repo f pinfo cfn ci ps +++
-              h1 << font! [color blue] << f +++
-              h2 << ("Patch:  "++just_name pinfo) +++
-              font! [face "Courier"] <<
-              markup_html (repo++"*"++f) pinfo cfn ci ps mk)
-
-markup_html :: FilePath -> PatchInfo -> FilePath
-            -> PatchInfo -> [PatchInfo] -> MarkedUpFile -> Html
-markup_html _ _ _ _ _ [] = p << ""
-markup_html f pinfo cfn ci ps ((l,None):mk) =
-    cl +++ font! [color black] << line_to_html (unpackPS l)
-           +++ (markup_html f pinfo cfn ci ps mk)
-    where cl = changelink f cfn ci $ None
-markup_html f pinfo cfn ci ps ((l,RemovedLine thei):mk) =
-    if pinfo == thei
-    then cl +++ font! [color red] << line_to_html (unpackPS l)
-             +++ (markup_html f pinfo cfn ci ps mk)
-    else if is_old_patch pinfo ps thei
-    then markup_html f pinfo cfn ci ps mk
-    else markup_html f pinfo cfn ci ps mk
-    where cl = changelink f cfn ci $ RemovedLine thei
-markup_html f pinfo cfn ci ps ((l,AddedLine thei):mk) =
-    if pinfo == thei
-    then cl +++ font! [color green] << line_to_html (unpackPS l)
-             +++ (markup_html f pinfo cfn ci ps mk)
-    else if is_old_patch pinfo ps thei
-    then cl +++ font! [color black] << line_to_html (unpackPS l)
-             +++ (markup_html f pinfo cfn ci ps mk)
-    else markup_html f pinfo cfn ci ps mk
-    where cl = changelink f cfn ci $ AddedLine thei
-markup_html f pinfo cfn ci ps ((l,AddedRemovedLine add removed):mk) =
-    if pinfo == removed
-    then cl +++ font! [color red] << line_to_html (unpackPS l)
-             +++ (markup_html f pinfo cfn ci ps mk)
-    else if pinfo == add
-    then cl +++ font! [color green] << line_to_html (unpackPS l)
-             +++ (markup_html f pinfo cfn ci ps mk)
-    else if is_old_patch pinfo ps add && (not $ is_old_patch pinfo ps removed)
-    then cl +++ font! [color black] << line_to_html (unpackPS l)
-             +++ markup_html f pinfo cfn ci ps mk
-    else markup_html f pinfo cfn ci ps mk
-    where cl = changelink f cfn ci $ AddedRemovedLine add removed
-
-changelink :: FilePath -> FilePath -> PatchInfo -> LineMark -> Html
-changelink f cfn ci (RemovedLine pinfo) =
-    font ! [color black] << "+" +++
-             (((toHtml $ hotlink ("darcs?"++f++"*"++make_filename pinfo
-                                  ++"*"++cfn++"*"++make_filename ci)
-                [toHtml "-"])
-               ! [thestyle "text-decoration:none"]) +++
-              spaceHtml)
-changelink f cfn ci (AddedLine pinfo) =
-    font ! [color black] <<
-             (((toHtml $ hotlink ("darcs?"++f++"*"++make_filename pinfo
-                                  ++"*"++cfn++"*"++make_filename ci) [toHtml "+"])
-               ! [thestyle "text-decoration:none"]) +++
-              "-" +++ spaceHtml)
-changelink f cfn ci (AddedRemovedLine add removed) =
-    font ! [color black] <<
-             (((toHtml $ hotlink ("darcs?"++f++"*"++make_filename add
-                                  ++"*"++cfn++"*"++make_filename ci)
-                [toHtml "+"])
-               ! [thestyle "text-decoration:none"]) +++
-              ((toHtml $ hotlink ("darcs?"++f++"*"++make_filename removed
-                                  ++"*"++cfn++"*"++make_filename ci)
-                [toHtml "-"])
-               ! [thestyle "text-decoration:none"]) +++
-              spaceHtml)
-changelink _ _ _ _ =
-    font ! [color black] << "+-" +++ spaceHtml
-
-is_old_patch :: PatchInfo -> [PatchInfo] -> PatchInfo -> Bool
-is_old_patch now (i:is) this =
-    if this == now then False
-    else if i == now then False
-    else if i == this then True
-    else is_old_patch now is this
-is_old_patch _ [] _ = impossible
-
-line_to_html :: String -> Html
-line_to_html "" = br
-line_to_html (' ':s) = spaceHtml +++ line_to_html s
-line_to_html ('\t':s) = spaceHtml +++ spaceHtml +++ line_to_html s
-line_to_html (c:s) = c +++ line_to_html s
-\end{code}
-
-\begin{code}
-htmlError :: String -> Html
-htmlError e
-      = header
-        << thetitle
-           << ("Error: "++e)
-   +++ body ! [bgcolor "#aaff88"] << (h1 << "Error! "+++br+++e)
-\end{code}
-
-\begin{code}
-nav :: String -> FilePath -> PatchInfo -> FilePath -> PatchInfo -> [PatchInfo] -> Html
-nav repo f pinfo cfn ci ps =
-    let
-      b = case before_pi pinfo ps of
-          Nothing -> "darcs?"++repo++"*"
-          Just bi -> "darcs?"++repo++"*"++f++"*"++make_filename bi++
-                     "*"++cfn++"*"++make_filename ci
-      a = case after_pi pinfo ps of
-          Nothing -> "darcs?"++repo++"*"
-          Just ai -> "darcs?"++repo++"*"++f++"*"++make_filename ai++
-                     "*"++cfn++"*"++make_filename ci
-    in
-    table ! [border 0] << ((td ! [align "left"] <<
-                            hotlink b [h4 << "Previous patch"])
-                           `beside`
-                           (td ! [align "center"] <<
-                            hotlink ("darcs?"++repo++"*") [h4 << "Home"])
-                           `beside`
-                           (td ! [align "right"] <<
-                            hotlink a [h4 << "Next patch"]))
-
-before_pi :: PatchInfo -> [PatchInfo] -> Maybe PatchInfo
-before_pi _ [] = Nothing
-before_pi _ [_] = Nothing
-before_pi pinfo (b:it:ps)
-    | it == pinfo = Just b
-    | otherwise = before_pi pinfo (it:ps)
-after_pi :: PatchInfo -> [PatchInfo] -> Maybe PatchInfo
-after_pi _ [] = Nothing
-after_pi _ [_] = Nothing
-after_pi pinfo (it:a:ps)
-    | it == pinfo = Just a
-    | otherwise = after_pi pinfo (a:ps)
-\end{code}
-
-\begin{code}
-get_reponame :: [(String,String)] -> (String,String)
-get_reponame env = let query = get_query env in
-    if not $ '*' `elem` query
-    then ("Error","Bad reponame etc: "++query)
-    else case break (=='*') query of
-         ("",_) -> ("Error","Empty reponame: "++query)
-         (reponame,star_pnfn) -> (reponame, tail star_pnfn)
-\end{code}
-
-\begin{code}
-get_filename_and_patchname :: String -> [String]
-get_filename_and_patchname query =
-  case length (filter (=='*') query) of
-  3 -> case break (=='*') query of
-       (f,q') ->
-           case break (=='*') $ tail q' of
-           (pn,q'') ->
-               case break (=='*') $ tail q'' of
-               (cfn,cn) -> [f,pn,cfn,tail cn]
-  1 -> case break (=='*') query of
-       (f,pat) -> [f,tail pat]
-  _ -> ["Error","Bad filename and patchname: "++query]
-\end{code}
-
-\begin{code}
-pop_to_html :: String -> Population -> Html
-pop_to_html before (Pop pinfo (PopDir _ pops)) =
-    foldl (+++) noh $ map (p2h before pinfo "./" noh) $ sort pops
-    where noh = toHtml ""
-pop_to_html _ _ = bug "Bug in pop_to_html"
-p2h :: String -> PatchInfo -> FilePath -> Html -> PopTree -> Html
-p2h before pinfo dir indent (PopFile info) =
-    indent +++
-    hotlink ("darcs?"++before++fullf++"*"++make_filename pinfo++"*"++cn++"*"++cp) [toHtml f] +++
-    file_change+++br
-        where f = unpackPS $ nameI info
-              fullf = dir ++ f
-              cn = unpackPS $ fromJust $ creationNameI info
-              cp = make_filename $ fromJust $ createdByI info
-              file_change = if modifiedByI info == pinfo
-                            then toHtml $ " "++show (modifiedHowI info)
-                            else toHtml ""
-p2h before pinfo dir indent (PopDir info pops) =
-    foldl (+++) (indent +++ toHtml thisdir +++ dir_change +++ br) $
-          map (p2h before pinfo fulldir (indent+++indmore)) $ sort pops
-    where fulldir = dir ++ thisdir
-          thisdir = unpackPS (nameI info) ++ "/"
-          indmore = spaceHtml +++ spaceHtml +++ spaceHtml +++ spaceHtml
-          dir_change = if modifiedByI info == pinfo
-                       then toHtml $ " "++show (modifiedHowI info)
-                       else toHtml ""
-\end{code}
-
-\begin{code}
-get_patchinfo_from_name :: String -> [(PatchInfo,Maybe Patch)] -> Maybe PatchInfo
-get_patchinfo_from_name _ [] = Nothing
-get_patchinfo_from_name n ((pinfo,_):pps) =
-  if n == make_filename pinfo then Just pinfo
-  else get_patchinfo_from_name n pps
-\end{code}
-
-\begin{code}
-get_query :: [(String,String)] -> String
-get_query [] = ""
-get_query (("QUERY_STRING",query):_) = query
-get_query (_:as) = get_query as
-\end{code}
-
-
-
rmfile ./darcs_cgi.lhs
}

Inconsistent repo!
HACK pion:~/playground/darcs$ darc  s repair

darcs failed:  Couldn't read patch Sun Oct 20 21:01:05 ADT 2002  droundy at abridgegame.org
  * Initial version of darcs.

HACK pion:~/playground/darcs$ df .
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/hda3             17839628  15448328   2391300  87% /home
HACK pion:~/playground/darcs$ darsc o    cs optimize
Done optimizing!
HACK pion:~/playground/darcs$ darcs version

darcs failed:  Invalid command 'version'!

Usage: darcs COMMAND ...
Commands:
  initialize    Initialize a new source tree as a darcs repository.
  get           Get a repository.
  add           Add one or more new files or directories.
  remove        Remove one or more files or directories from the repository.
  mv            Move a file or directory to a different location or name.
  whatsnew      Display unrecorded changes in the working directory.
  record        Record changes as a named patch.
  unrecord      Unrecord a named patch.
  rerecord      Add some changes to an already recorded patch.
  revert        Revert to recorded version.
  unrevert      Undo the last revert operation.
  pull          Pull patches from another repo.
  unpull        Unpull a named patch.
  rollback      Roll back a named patch.
  send          Send via email a bundle of one or more patches.
  apply         Apply patches to a repo.
  push          Push patches into another repo.
  replace       Replace a token with a new value for that token.
  tag           Tag the contents of a repo with a given version name.
  setpref       Set the value for a preferences thingy.
  diff          Create a diff between two versions of the repository.
  changes       Gives a human-readable list of changes between versions.
  annotate      Display useful information about the repository history.
  optimize      Optimize your repository.
  check         Check the repository for consistency.
  resolve       Resolve conflicts.
  dist          Create a distribution tarball.
  trackdown     Find the most recent version which passes a test.
  repair        Repair a corrupted repository.
  reportbug     Report a bug in darcs.
Type "darcs --extended-help" for a more technical description of some of these commands.
Type "darcs COMMAND --help" for help on a particular command.
Type "darcs --version" to see the darcs version number and type "darcs --exact-version"
    to get the precise contents of the repository from which this darcs was compiled.

HACK pion:~/playground/darcs$ darcs version[1 at -[1 at -
1.0.0rc2
HACK pion:~/playground/darcs$ darcs --version[1 at e[1 at x[1 at a[1 at c[1 at t[1 at 0[1 at -
darcs compiled on Oct  4 2004, at 14:53:10
unknown

HACK pion:~/playground/darcs$ 




More information about the darcs-users mailing list