[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[1P[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