【问题标题】:How to use the darcs library to query information about patches?如何使用darcs库查询补丁信息?
【发布时间】:2012-10-17 19:21:43
【问题描述】:

我想编写一个 Haskell 程序来查询有关 darcs 存储库的信息。我宁愿直接使用 darcs 库,而不是调用 darcs 可执行文件并解析结果。 said to be“正在进行大量工作”和“缺乏稳定的 API”,但似乎可用。

我想我可以通过研究 darcsden 源代码来回答我的问题,例如,从 this module 开始,但我认为如果有知识的人提供评论介绍来补充这样的研究,这不仅对我有帮助.

所以,这是一个具体的例子。

如何计算给定文件的最新补丁以及补丁的日期、作者和名称?如果您解释解决方案中使用的关键库函数,这将非常有用。


编辑:

这里有一些对不熟悉 darcs 源代码的人可能不明显的评论。我是从Jason Dagit's master thesis 学来的,希望对理解 Ganesh 给出的答案有所帮助。

在 Darcs 中,补丁有一个前后上下文,表示应用补丁之前和之后存储库的状态。在源代码中,这些上下文是在补丁类型上使用幻像类型建模的。这些幻像类型被称为见证者,seal2 用于摆脱它们。

在补丁列表中,只有第一个前置上下文和最后一个后置上下文在类型中表示。所有其他上下文都使用存在类型隐藏。 Darcs 定义了前向列表(称为 FL)和反向列表(称为 RL)。反向列表以反向(按时间顺序)顺序存储补丁(由 darcs 完成的模补丁重新排序)。反向列表可用于访问头部位置的最新补丁。所有名称中带有 RL 的函数都会创建或操作此类反向列表。

【问题讨论】:

  • 您要使用最新版本(2.8.2)还是最新的不稳定版本?至少在模块结构方面,2.10 正在进行一些重大的重组。
  • 我要使用的版本取决于 2.10 的发布时间。如果它会在未来一两个月内发布,我更喜欢 2.10。如果只是模块结构不同,我认为将任一版本的解决方案转移到另一个版本应该很容易。因此,请随意给出 2.10 的未来证明答案,并暗示 2.8 中的不同之处。
  • 2.10 不太可能在未来一两个月内推出,但有望在年底左右推出。

标签: haskell darcs


【解决方案1】:
-- 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)

【讨论】:

  • 谢谢!在 2.8.2 中,withRepositoryDirectory 会显示一个 DarcsFlags 列表,您在其中传递 YesUseCache。唯一与缓存相关的标志似乎是 NoCache,这表明传递空列表与 YesUseCache 具有相同的行为。对吗?
  • 我编辑了我的问题,包括对“证人”和反向列表的一些(希望是准确的)评论。我希望它们能让不熟悉 Darcs 源代码的人更容易获得您的答案。
  • 谢谢!我确实认为我应该自己对它们进行一些评论,但没有考虑。
  • 是否存在用于 Darcs 的 C/C++ API?
  • 不,它只是 Haskell。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-26
  • 1970-01-01
  • 2012-09-30
  • 1970-01-01
  • 2014-07-19
  • 1970-01-01
相关资源
最近更新 更多