private static void DiffCellsCaseInserted(
            DiffResult <ExcelRow> result, ExcelSheetDiff sheetDiff, Dictionary <int, ExcelColumnStatus> columnStatusMap)
        {
            var row = sheetDiff.CreateRow();

            var columnIndex = 0;

            foreach (var cell2 in result.Obj2.Cells)
            {
                var cell1 = new ExcelCell(string.Empty, cell2.OriginalColumnIndex, cell2.OriginalRowIndex);
                row.CreateCell(cell1, cell2, columnIndex, ExcelCellStatus.Added);

                columnIndex++;
            }
        }
        private static void DiffCellsCaseEqual(
            DiffResult <ExcelRow> result, ExcelSheetDiff sheetDiff, Dictionary <int, ExcelColumnStatus> columnStatusMap)
        {
            var row = sheetDiff.CreateRow();

            var equalizedCells = EqualizeColumnCount(result.Obj1.Cells, result.Obj2.Cells, columnStatusMap);
            var columnIndex    = 0;

            foreach (var pair in equalizedCells)
            {
                var srcCell = pair.Item1;
                var dstCell = pair.Item2;

                if (srcCell != null && dstCell != null)
                {
                    var status = srcCell.Value.Equals(dstCell.Value) ? ExcelCellStatus.None : ExcelCellStatus.Modified;
                    if (columnStatusMap[columnIndex] == ExcelColumnStatus.Deleted)
                    {
                        status = ExcelCellStatus.Removed;
                    }
                    else if (columnStatusMap[columnIndex] == ExcelColumnStatus.Inserted)
                    {
                        status = ExcelCellStatus.Added;
                    }

                    row.CreateCell(srcCell, dstCell, columnIndex, status);
                }
                else if (srcCell != null && dstCell == null)
                {
                    dstCell = new ExcelCell(string.Empty, srcCell.OriginalColumnIndex, srcCell.OriginalColumnIndex);
                    row.CreateCell(srcCell, dstCell, columnIndex, ExcelCellStatus.Removed);
                }
                else if (srcCell == null && dstCell != null)
                {
                    srcCell = new ExcelCell(string.Empty, dstCell.OriginalColumnIndex, dstCell.OriginalColumnIndex);
                    row.CreateCell(srcCell, dstCell, columnIndex, ExcelCellStatus.Added);
                }
                else
                {
                    srcCell = new ExcelCell(string.Empty, 0, 0);
                    dstCell = new ExcelCell(string.Empty, 0, 0);
                    row.CreateCell(srcCell, dstCell, columnIndex, ExcelCellStatus.None);
                }

                columnIndex++;
            }
        }
        public void DoDiff()
        {
            var total = src.files.Union(dst.files).ToList();

            total.Sort();

            results.Clear();
            resultRevisions.Clear();

            var md5Hash = MD5.Create();

            foreach (var file in total)
            {
                var res    = new DiffResult <string>(file, file, DiffStatus.Equal);
                var consrc = src.files.Contains(file);
                var condst = dst.files.Contains(file);
                if (consrc && !condst)
                {
                    res.Obj2   = null;
                    res.Status = DiffStatus.Deleted;
                }
                else if (!consrc && condst)
                {
                    res.Obj1   = null;
                    res.Status = DiffStatus.Inserted;
                }

                if (res.Status == DiffStatus.Equal)
                {
                    // check md5 first
                    //var hash1 = md5Hash.ComputeHash(File.OpenRead(src.root + file));
                    //var hash2 = md5Hash.ComputeHash(File.OpenRead(dst.root + file));
                    if (!DiffUtil.FilesAreEqual(src.root + file, dst.root + file))
                    {
                        res.Status = DiffStatus.Modified;
                    }
                }

                results.Add(res);
            }

            DstDataGrid.refreshData();
            SrcDataGrid.refreshData();
        }
        private void DoVersionDiff_Click(object sender, RoutedEventArgs e)
        {
            if (string.IsNullOrEmpty(FilterCommits.Text))
            {
                TextTip.Content = "需要填写单号,多个单号空格隔开";
                return;
            }
            if (src.files.Count <= 0)
            {
                TextTip.Content = "拖目标文件夹进来,或目标文件夹下没有xls";
                return;
            }

            Collection <SvnLogEventArgs> logitems;

            DateTime startDateTime = DateTime.Now.AddDays(-60);
            DateTime endDateTime   = DateTime.Now;
            var      svnRange      = new SvnRevisionRange(new SvnRevision(startDateTime), new SvnRevision(endDateTime));

            List <SvnRevisionCombo> revisions = new List <SvnRevisionCombo>();

            var files = new Dictionary <string, RevisionRange>();

            var filter = FilterCommits.Text.Split(" #".ToArray(), StringSplitOptions.RemoveEmptyEntries);

            var sfilter   = string.Join("|", filter);
            var regfilter = new Regex(sfilter);

            using (SvnClient client = new SvnClient()) {
                client.Authentication.SslServerTrustHandlers += delegate(object _sender, SharpSvn.Security.SvnSslServerTrustEventArgs _e) {
                    _e.AcceptedFailures = _e.Failures;
                    _e.Save             = true; // Save acceptance to authentication store
                };

                if (client.GetUriFromWorkingCopy(src.root) != null)
                {
                    SvnInfoEventArgs info;
                    client.GetInfo(src.root, out info);
                    var uri = info.Uri;

                    var rootPath = info.Path;

                    client.GetLog(uri, new SvnLogArgs(svnRange), out logitems);

                    foreach (var logentry in logitems)
                    {
                        var author   = logentry.Author;
                        var message  = logentry.LogMessage;
                        var date     = logentry.Time;
                        var revision = logentry.Revision;

                        if (regfilter.IsMatch(message))
                        {
                            foreach (var filepath in logentry.ChangedPaths)
                            {
                                var path = filepath.Path;

                                RevisionRange minmax = null;
                                if (!files.TryGetValue(path, out minmax))
                                {
                                    minmax = new RevisionRange()
                                    {
                                        min = revision, max = revision, file = path
                                    };
                                    files[path] = minmax;
                                }
                                if (revision > minmax.max)
                                {
                                    minmax.max = revision;
                                }
                                if (revision < minmax.min)
                                {
                                    minmax.min = revision;
                                }
                            }
                        }
                    }
                }
            }

            results.Clear();
            resultRevisions.Clear();

            foreach (var file in files.Keys)
            {
                var range = files[file];
                var res   = new DiffResult <string>(file + "-" + range.min, file + "-" + range.max, DiffStatus.Modified);

                results.Add(res);
                resultRevisions.Add(range);
            }

            DstDataGrid.refreshData();
            SrcDataGrid.refreshData();
        }