Как определить, какие файлы были вручную объединены в истории Mercurial? - PullRequest
3 голосов
/ 18 февраля 2011

Я являюсь частью команды, недавно использующей Mercurial, и мы определили, что при слиянии возникает гораздо больше ошибок в файлах, которые объединяются вручную.Можно ли из журналов Mercurial (т.е. после того, как кто-то сделал слияние и перенес набор изменений в центральное хранилище), чтобы определить, какие файлы были объединены вручную?

Ответы [ 2 ]

3 голосов
/ 18 февраля 2011

Обратите внимание, что я понятия не имею, если это надежно. Кроме того, для этого требуется копия моей еще не законченной библиотеки Mercurial для .NET, которая, вероятно, работает только в Windows и довольно грубая по краям.

Примечание. Я предполагаю, что под словом "были объединены вручную" вы подразумеваете "файлы, которые Mercurial не объединял для нас автоматически"

Такой файл все еще может быть частично или полностью автоматизирован с помощью внешнего инструмента, но если приведенное выше предположение достаточно хорошо, читайте дальше.

Однако я эффективно провел все слияния в тестовом репозитории, повторно выполнив слияния и попросив Mercurial использовать только свой внутренний инструмент слияния, который оставляет файлы неразрешенными, если Mercurial не может автоматически слить их, затем сообщите обо всех неразрешенных файлах, очистите слияние и перейдите к следующему набору изменений слияния.

Библиотека, в которой вы нуждаетесь (только в форме исходного кода на данный момент, я говорил вам, что она еще не закончена):

Я прикрепил zip-файл внизу со всем, тестовым хранилищем, скриптом и двоичной копией библиотеки.

Сценарий (я использовал LINQPad , чтобы написать и проверить это, вывод из репозитория test следует):

void Main()
{
    var repo = new Repository(@"c:\temp\repo");
    var mergeChangesets = repo.Log(new LogCommand()
        .WithAdditionalArgument("-r")
        .WithAdditionalArgument("merge()")).Reverse().ToArray();

    foreach (var merge in mergeChangesets)
    {
        Debug.WriteLine("analyzing merge #" + merge.RevisionNumber +
            " between revisions #" + merge.LeftParentRevision +
            " and #" + merge.RightParentRevision);
        // update to left parent
        repo.Update(merge.LeftParentHash);
        try
        {
            // perform merge with right parent
            var mergeCmd = new MergeCommand();
            mergeCmd.WithRevision = merge.RightParentHash;
            repo.Execute(mergeCmd);

            // get list of unresolved files
            var resolveCmd = new ResolveCommand();
            repo.Execute(resolveCmd);
            var unresolvedFiles = new List<string>();
            using (var reader = new StringReader(resolveCmd.RawStandardOutput))
            {
                string line;
                while ((line = reader.ReadLine()) != null)
                    if (line.StartsWith("U "))
                        unresolvedFiles.Add(line.Substring(2));
            }

            // report
            if (unresolvedFiles.Count > 0)
            {
                Debug.WriteLine("merge changeset #" + merge.RevisionNumber +
                    " between revisions #" + merge.LeftParentRevision +
                    " and #" + merge.RightParentRevision + " had " +
                    unresolvedFiles.Count + " unresolved file(s)");
                foreach (string filename in unresolvedFiles)
                {
                    Debug.WriteLine("  " + filename);
                }
            }
        }
        finally
        {
            // get repository back to proper state
            repo.Update(merge.LeftParentHash, new UpdateCommand().WithClean());
        }
    }
}

public class MergeCommand : MercurialCommandBase<MergeCommand>
{
    public MergeCommand()
        : base("merge")
    {
    }

    [NullableArgumentAttribute(NonNullOption = "--rev")]
    public RevSpec WithRevision
    {
        get;
        set;
    }

    public override IEnumerable<string> Arguments
    {
        get
        {
            foreach (var arg in base.Arguments)
                yield return arg;
            yield return "--config";
            yield return "ui.merge=internal:merge";
        }
    }

    protected override void ThrowOnUnsuccessfulExecution(int exitCode,
        string standardOutput, string standardErrorOutput)
    {
        if (exitCode != 0 && exitCode != 1)
            base.ThrowOnUnsuccessfulExecution(exitCode, standardOutput,
                standardErrorOutput);
    }
}

public class ResolveCommand : MercurialCommandBase<MergeCommand>
{
    public ResolveCommand()
        : base("resolve")
    {
    }

    public override IEnumerable<string> Arguments
    {
        get
        {
            foreach (var arg in base.Arguments)
                yield return arg;
            yield return "--list";
        }
    }
}

Пример вывода:

analyzing merge #7 between revisions #5 and #6
analyzing merge #10 between revisions #9 and #8
merge changeset #10 between revisions #9 and #8 had 1 unresolved file(s)
  test1.txt

Zip-файл со всем (скрипт LINQPad, сборка Mercurial.Net, иди скомпилируй его, если не доверяешь мне, и тестовый репозиторий, с которым я выполнил выше):

BIG CAVEAT : Запустите это только в клоне вашего хранилища! Я не буду нести ответственность, если это повредит ваш репозиторий, однако вряд ли я думаю, что это будет.

2 голосов
/ 24 февраля 2011

Это вариант сценария оболочки Lasses ответ:

#!/bin/bash

test "$1" = "--destroy-my-working-copy" || exit

hg log -r 'merge()' --template '{parents} {rev}\n' | sed -e 's/[0-9]*://g' | while read p1 p2 commit
do
        echo "-------------------------"
        echo examine $commit
        LC_ALL=C hg up -C -r $p1 >/dev/null
        LC_ALL=C hg merge -r 26 --config ui.merge=internal:merge 2>&1 | grep failed
done

hg up -C -r tip > /dev/null

Пример вывода:

> mergetest.sh --destroy-my-working-copy
-------------------------
examine 7
-------------------------
examine 11
-------------------------
examine 23
-------------------------
examine 31
-------------------------
examine 37
merging test.py failed!
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...