11

Darcs リポジトリに関する情報を照会する Haskell プログラムを作成したいと考えています。darcs 実行可能ファイルを呼び出して結果を解析する代わりに、darcs ライブラリを直接使用したいと思います。「非常に多くの作業が進行中」であり、「安定した API が不足している」と言われていますが、使用可能のようです

このモジュールから始めてdarcsdenのソースコードを勉強することで私の質問に答えることができると思いますが、知識のある人がそのような研究を補足するためにコメント付きの紹介を提供してくれると私だけでなく役立つかもしれないと思います.

というわけで、具体例を挙げます。

特定のファイルについて、そのファイルに影響を与えた最新のパッチと、パッチの日付、作成者、および名前を計算するにはどうすればよいですか? ソリューションで使用されている主要なライブラリ関数を説明すると、非常に役立ちます。


編集:

darcs のソース コードに慣れていない人にとっては明らかではないかもしれないいくつかの注意事項を次に示します。私はジェイソン・ダギットの修士論文からそれらを学びました.ガネーシュが与えた答えを理解するのに役立つことを願っています.

Darcs では、パッチには、パッチの適用前後のリポジトリの状態を表す前後のコンテキストがあります。ソース コードでは、これらのコンテキストは、パッチのタイプでファントム タイプを使用してモデル化されます。これらの幻のタイプは目撃者と呼ばれseal2、それらを取り除くために使用されます。

パッチのリストでは、最初のプレコンテキストと最後のポストコンテキストのみがタイプで表されます。他のすべてのコンテキストは、存在型を使用して隠されています。Darcs では、順リスト (FL と呼ばれる) と逆リスト (RL と呼ばれる) が定義されています。逆順リストはパッチを逆 (時系列) に保存します (darcs によってモジュロパッチの並べ替えが行われます)。リバース リストを使用して、先頭位置にある最新のパッチにアクセスできます。名前に RL を含むすべての関数は、そのような逆リストを作成または操作します。

4

1 に答える 1

4
-- This works with darcs 2.9.5 (a tag in the development repo
-- at http://darcs.net/screened).
--
-- It should work with darcs 2.8.2 with the following changes:
--  - some minor namespace changes
--  - change withRepositoryDirectory to pass [] instead of YesUseCache
--  - comment out the line below that uses the "patch index"

import Control.Applicative ( (<$>) )

import Darcs.Patch.Info ( PatchInfo )
import Darcs.Patch.Inspect ( listTouchedFiles )
import Darcs.Patch.PatchInfoAnd ( info )
import Darcs.Patch.Set ( newset2RL )
import Darcs.Patch.Witnesses.Ordered ( mapRL )
import Darcs.Patch.Witnesses.Sealed ( seal2, unseal2 )

import Darcs.Repository
    ( withRepositoryDirectory, RepoJob(..), readRepo )
import Darcs.Repository.FileMod ( filterPatches )
import Darcs.Repository.Flags ( UseCache(..) )

import Data.Maybe ( listToMaybe )

getChange
    :: FilePath                -- ^repository directory
    -> FilePath                -- ^file path
    -> IO (Maybe PatchInfo)    -- ^patch metadata
getChange repoDir fileName =

    -- Select the repository from repositoryDirectory.
    --
    -- The function parameter to 'RepoJob' needs to be polymorphic
    -- in the underlying patch type (darcs-1 or darcs-2).

    withRepositoryDirectory YesUseCache repoDir $ RepoJob $ \repo -> do

    -- 'readRepo' gives us a PatchSet, a lazy witnessed list of all
    -- the patches structured by "clean tags".
    --
    -- We use 'newset2RL' to get rid of the tag structure as we don't
    -- need it, and 'mapRL seal2' to get rid of the witnesses which we
    -- also don't need. The result is of type '[Sealed2 p]', where 'p'
    -- is the underlying patch type of the repository we are reading
    -- (either darcs-1 or darcs-2)

    patches <- mapRL seal2 . newset2RL <$> readRepo repo


    -- Use the recently introduced "patch index" to filter the list of
    -- patches from the repo down to ones that just touch 'fileName'.
    --
    -- This step is optional: we can remove it and the result will be
    -- the same, but substantially slower on large repositories where
    -- the patch we want is far back in the repo.

    patches <- filterPatches repo [fileName] patches

    -- Use 'filter' and 'listToMaybe' to get the first patch that touches
    -- 'fileName'.
    --
    -- The filter is superfluous in this simple case if the patch
    -- index was used, but doesn't cost much if so.
    --
    -- Note that this doesn't track renames, so isn't suitable for
    -- finding anything but the last patch that touched 'fileName'.
    --
    -- 'unseal2' is used to lift a function that works on witnessed
    -- patches to one that works on "sealed" patches.

    let wanted = unseal2 (\patch -> fileName `elem` listTouchedFiles patch)
    let thepatch = listToMaybe . filter wanted $ patches

    -- Finally, return the metadata of the patch.
    --
    -- Things get a little bit more complex if we want to deal
    -- with the contents of the patch, because the specific
    -- patch type isn't known statically - it might be
    -- darcs-1 or darcs-2.
    --
    -- The best approach is to write a polymorphic function that
    -- can accept any instance of 'RepoPatch'.

    return (fmap (unseal2 info) thepatch)
于 2012-10-18T12:09:22.453 に答える