이름 판단을 MergeNote.AuthorOf 로 모아 머지 주석과 보고서가 같은 이름을 쓴다. 이름이 비면 줄 자체를 넣지 않는다. 검사 8건 추가.
154 lines
6.1 KiB
C#
154 lines
6.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using MergeHub.Models;
|
|
|
|
namespace MergeHub.Services
|
|
{
|
|
/// <summary>
|
|
/// 비교 결과를 <b>메모장으로 열어 읽을 수 있는 글</b>로 만든다.
|
|
///
|
|
/// 왜 글로 뽑나 - 결과를 남에게 보내거나 결재에 붙일 때 화면을 캡처하는 것 말고는 방법이 없었다.
|
|
/// 캡처는 검색도 안 되고 줄 번호를 짚어 말하기도 어렵다.
|
|
///
|
|
/// 화면 없이 검사할 수 있어야 하므로 <b>글을 만드는 일만</b> 여기서 한다.
|
|
/// 어디에 저장할지 묻는 것은 화면 쪽 일이다.
|
|
/// </summary>
|
|
public static class CompareReport
|
|
{
|
|
private const string Rule = "----------------------------------------------------------------";
|
|
|
|
/// <summary>파일 비교 결과.</summary>
|
|
public static string ForFile(string leftLabel, string rightLabel,
|
|
IReadOnlyList<MergeLine> lines, DateTime when, string? author = null)
|
|
{
|
|
var text = new StringBuilder();
|
|
|
|
Head(text, "파일 비교 결과", leftLabel, rightLabel, when, author);
|
|
|
|
var changed = 0;
|
|
var added = 0;
|
|
var removed = 0;
|
|
|
|
foreach (var line in lines)
|
|
{
|
|
if (line.IsMergeNote || line.IsIgnored) continue;
|
|
|
|
switch (line.State)
|
|
{
|
|
case MergeLineState.Changed: changed++; break;
|
|
case MergeLineState.LocalOnly: added++; break;
|
|
case MergeLineState.BaseOnly: removed++; break;
|
|
}
|
|
}
|
|
|
|
text.AppendLine($"요약: 총 {lines.Count} 줄 · 다름 {changed} · 오른쪽에만 {added} · 왼쪽에만 {removed}");
|
|
text.AppendLine();
|
|
|
|
if (changed + added + removed == 0)
|
|
{
|
|
text.AppendLine("다른 줄이 없습니다.");
|
|
return text.ToString();
|
|
}
|
|
|
|
text.AppendLine("다른 줄");
|
|
text.AppendLine(Rule);
|
|
|
|
foreach (var line in lines)
|
|
{
|
|
if (line.IsMergeNote || line.IsIgnored) continue;
|
|
if (line.State == MergeLineState.Same) continue;
|
|
|
|
// 줄 번호는 <b>양쪽을 다 적는다.</b> 한쪽에만 있는 줄이 있어 번호가 어긋나므로,
|
|
// 하나만 적으면 파일에서 그 줄을 찾을 수 없다.
|
|
var number = $"{Number(line.BaseNumber)}/{Number(line.LocalNumber)}";
|
|
|
|
text.AppendLine($"[{number}] {StateName(line.State)}");
|
|
if (line.HasBase) text.AppendLine(" - " + line.BaseText);
|
|
if (line.HasLocal) text.AppendLine(" + " + line.LocalText);
|
|
}
|
|
|
|
return text.ToString();
|
|
}
|
|
|
|
/// <summary>폴더 비교 결과.</summary>
|
|
public static string ForFolder(string leftFolder, string rightFolder,
|
|
FolderCompareResult result, DateTime when, string? author = null)
|
|
{
|
|
var text = new StringBuilder();
|
|
|
|
Head(text, "폴더 비교 결과", leftFolder, rightFolder, when, author);
|
|
text.AppendLine("요약: " + result.Summary);
|
|
if (result.Truncated) text.AppendLine("(항목이 너무 많아 도중에 멈춘 결과입니다)");
|
|
text.AppendLine();
|
|
|
|
var rows = new List<(string Status, string Path)>();
|
|
Collect(result.Items, rows);
|
|
|
|
if (rows.Count == 0)
|
|
{
|
|
text.AppendLine("다른 항목이 없습니다.");
|
|
return text.ToString();
|
|
}
|
|
|
|
text.AppendLine("다른 항목");
|
|
text.AppendLine(Rule);
|
|
|
|
foreach (var row in rows) text.AppendLine($"{row.Status,-12}{row.Path}");
|
|
|
|
return text.ToString();
|
|
}
|
|
|
|
/// <summary>폴더 트리를 훑어 "같음"이 아닌 <b>파일만</b> 모은다.</summary>
|
|
private static void Collect(IEnumerable<FolderCompareItem> items, List<(string, string)> rows)
|
|
{
|
|
foreach (var item in items)
|
|
{
|
|
if (item.IsDirectory)
|
|
{
|
|
Collect(item.Children, rows);
|
|
continue;
|
|
}
|
|
|
|
if (item.Status == FolderEntryStatus.Same) continue;
|
|
rows.Add((StatusName(item.Status), item.RelativePath));
|
|
}
|
|
}
|
|
|
|
/// <param name="author">
|
|
/// 뽑은 사람. 남에게 보내라고 만든 글이라 <b>누가 뽑았는지</b>가 없으면 받는 쪽이 되묻게 된다.
|
|
/// 비어 있으면 줄 자체를 넣지 않는다 - "만든 사람: " 만 덩그러니 있는 것보다 없는 편이 낫다.
|
|
/// </param>
|
|
private static void Head(StringBuilder text, string title, string left, string right, DateTime when,
|
|
string? author)
|
|
{
|
|
text.AppendLine($"MergeHub {title}");
|
|
text.AppendLine($"만든 때: {when:yyyy-MM-dd HH:mm:ss}");
|
|
if (!string.IsNullOrWhiteSpace(author)) text.AppendLine($"만든 사람: {author}");
|
|
text.AppendLine($"왼쪽 : {left}");
|
|
text.AppendLine($"오른쪽: {right}");
|
|
text.AppendLine(Rule);
|
|
}
|
|
|
|
private static string Number(int? value) => value is int n ? n.ToString() : "-";
|
|
|
|
private static string StateName(MergeLineState state) => state switch
|
|
{
|
|
MergeLineState.Changed => "다름",
|
|
MergeLineState.LocalOnly => "오른쪽에만",
|
|
MergeLineState.BaseOnly => "왼쪽에만",
|
|
_ => "같음"
|
|
};
|
|
|
|
private static string StatusName(FolderEntryStatus status) => status switch
|
|
{
|
|
FolderEntryStatus.Different => "다름",
|
|
FolderEntryStatus.CommentOnly => "주석만 다름",
|
|
FolderEntryStatus.Binary => "다름(이진)",
|
|
FolderEntryStatus.LeftOnly => "왼쪽에만",
|
|
FolderEntryStatus.RightOnly => "오른쪽에만",
|
|
_ => "같음"
|
|
};
|
|
}
|
|
}
|