static void Main(string[] args) { Log.ConsoleMode = true; int id = 0; var changeFiles = new List<ChangeFile>(); var options = new GenDiffArgs(); if (Parser.ParseArgumentsWithUsage(args, options)) { if (!string.IsNullOrEmpty(options.CL)) { // insert application code here var changeList = (from change in db.ChangeLists where change.CL == options.CL select change).FirstOrDefault(); if (changeList != null) id = changeList.Id; } if (!string.IsNullOrEmpty(options.file)) { var fileName = options.file.ToLower(); var files = (from file in db.ChangeFiles where file.ServerFileName.ToLower().Contains(fileName) && (id == 0 || file.ChangeListId == id) select file); foreach (var file in files) { changeFiles.Add(file); } } if (options.fileId > 0 && options.revisionId < 0) { var fileName = options.file.ToLower(); var files = (from file in db.ChangeFiles where file.Id == options.fileId && (id == 0 || file.ChangeListId == id) select file); foreach (var file in files) { changeFiles.Add(file); } } } var userName = Environment.GetEnvironmentVariable("USERNAME").Trim(); UserName = new UserName(userName, db); UserSettings = ReviewUtil.UserSettings(0, UserName.userName, db); if (changeFiles.Count > 0) { foreach (var changeFile in changeFiles) { DiffRevision(changeFile.ChangeListId, changeFile.Id, changeFile.ReviewRevision - 1, force); } } else if (id != 0) { if (options.fileId != 0 && options.revisionId >= 0) { DiffRevision(id, options.fileId, options.revisionId, force); } else { var gen = new DiffGenerator(db); gen.GenDiffFiles(id, UserName.userName, UserSettings, force); } } else { var gen = new DiffGenerator(db); var changelists = (from item in db.ChangeLists.AsNoTracking() where (item.Stage != (int)ChangeListStatus.Deleted) select item).OrderByDescending(x => x.TimeStamp); foreach (var item in changelists) { Log.Info("Generate diff files for {0} {1}", item.CL, item.Id); gen.GenDiffFiles(item.Id, UserName.userName, UserSettings, force); } } }
protected ChangeListDto GetChangeListForFile(int id, string userName, int fileId, UserSettingsDto settings) { var changeList = GetChangeList(id); var changeFile = GetChangeFile(changeList, fileId); var dto = new ChangeListDto(changeList, true); var changeFileDto = dto.changeFiles.Find(item => item.id == fileId); if (changeFile == null || changeFile.ChangeList == null) throw new ApplicationException(string.Format("Error creating ChangeListDto model for change list id: {0} cl: {1} file: {2}", changeList.Id, changeList.CL, fileId)); return new ChangeListDto(changeList, true); }
/// <summary> /// Computes and displays the diff between two distinct versions. Uses unix "diff" command to actually /// produce the diff. This is relatively slow operation and involves spooling the data into two temp /// files and running an external process. /// </summary> public string GenerateDiffFile(FileVersion left, FileVersion right, string clName, int baseReviewId, UserSettingsDto settings, bool force = false) { string outputFile = null; if (settings.diff.DefaultSettings) { outputFile = string.Format(@"{0}\{1}\{2}\{3}.{4}.htm", _diffFolderRoot, clName, left.FileId, left.Id, right.Id); if (File.Exists(outputFile)) { if (!force) return outputFile; File.Delete(outputFile); } } var useLeft = true; var useRight = true; var ignoreBase = false; if (left.Id == right.Id) { ignoreBase = true; var actionType = (SourceControlAction)Enum.ToObject(typeof(SourceControlAction), left.Action); switch (actionType) { case SourceControlAction.Add: case SourceControlAction.Branch: case SourceControlAction.Edit: case SourceControlAction.Integrate: case SourceControlAction.Rename: default: useLeft = false; break; case SourceControlAction.Delete: useRight = false; break; } } using (var leftFile = useLeft ? SaveToTempFile(left, ignoreBase) : EmptyTempFile()) using (var rightFile = useRight ? SaveToTempFile(right, ignoreBase) : EmptyTempFile()) { if (leftFile == null || rightFile == null) throw new ApplicationException(string.Format("Could not save temporary file for diffs. change list: {0} left file id: {1} right file id: {2}", clName, left.FileId, right.FileId)); string stderr = null; string result = null; if (ConfigurationManager.AppSettings.LookupValue("preDiff", false) && settings.diff.preDiff) { PreDiffFile(leftFile.FullName, rightFile.FullName); } result = DiffFiles(leftFile.FullName, rightFile.FullName, settings.diff.ignoreWhiteSpace, ref stderr); if (!string.IsNullOrEmpty(stderr)) { ErrorOut("Diff failed."); ErrorOut(stderr); return "Error Failed to generate diff. " + stderr; } using (var leftStream = new StreamCombiner(new StreamReader(leftFile.FullName))) using (var rightStream = new StreamCombiner(new StreamReader(rightFile.FullName))) using (var rawDiffStream = new StreamCombiner(result)) { var leftName = string.Format("{0}_{1}", Path.GetFileName(left.ChangeFile.ServerFileName), left.Id); var rightName = string.Format("{0}_{1}", Path.GetFileName(right.ChangeFile.ServerFileName), right.Id); if (string.IsNullOrEmpty(outputFile)) outputFile = string.Format(@"{0}\{1}\{2}\{3}.{4}.delete.{5}.htm", _diffFolderRoot, clName, left.FileId, left.Id, right.Id, this._random.Next()); GenerateFileDiffView(left.ReviewRevision, right.ReviewRevision, settings, leftStream, left.Id, leftName, rightStream, right.Id, rightName, rawDiffStream, clName, outputFile); GenerateDiffInfoFile(clName, left, right, baseReviewId); return outputFile; } } }
/// <summary> /// Generates the diff view for two file revisions. /// </summary> private string GenerateFileDiffView( int baseRevision, int diffRevision, UserSettingsDto settings, StreamCombiner baseFile, int baseId, string baseHeader, StreamCombiner diffFile, int diffId, string diffHeader, StreamCombiner rawDiff, string fileName, string outputFile) { var baseEncoder = GetEncoderForFile(fileName); var diffEncoder = GetEncoderForFile(fileName); var baseFileInfo = new DiffFileInfo(baseFile, baseEncoder, baseId, BaseOrDiff.Base); var diffFileInfo = new DiffFileInfo(diffFile, diffEncoder, diffId, BaseOrDiff.Diff); // Line Stamp format var baseScriptIdPrefix = "Base-" + EncodeLinePrefix(baseRevision, diffRevision, baseId, diffId, baseId); var diffScriptIdPrefix = "Diff-" + EncodeLinePrefix(baseRevision, diffRevision, baseId, diffId, diffId); var edgePrefix = "Edge-" + EncodeLinePrefix(baseRevision, diffRevision, baseId, diffId, diffId); var rowGroups = new List<HtmlTableRowGroup>(); var lastBaseLine = "1"; var lastDiffLine = "1"; foreach (var diffItem in DiffItem.EnumerateDifferences(rawDiff)) { var atEnd = diffItem.BaseLineCount == int.MaxValue; var baseLines = new List<Line>(); for (var i = 0; i < diffItem.BaseLineCount && baseFileInfo.MoveNextLine(); ++i) baseLines.Add(new Line { LineNum = baseFileInfo.CurLineNum.ToString(CultureInfo.InvariantCulture), LineText = baseFileInfo.CurLine }); var diffLines = new List<Line>(); for (var i = 0; i < diffItem.DiffLineCount && diffFileInfo.MoveNextLine(); ++i) diffLines.Add(new Line { LineNum = diffFileInfo.CurLineNum.ToString(CultureInfo.InvariantCulture), LineText = diffFileInfo.CurLine }); var baseLinesLength = baseLines.Count(); var diffLinesLength = diffLines.Count(); // The end is the only case where the DiffInfo line counts may be incorrect. If there are in fact // zero lines then just continue, which should cause the foreach block to end and we'll continue // like the DiffItem never existed. if (atEnd && diffItem.DiffType == DiffType.Unchanged && baseLinesLength == 0 && diffLinesLength == 0) continue; var rowGroup = new HtmlTableRowGroup(diffItem.DiffType); for (var i = 0; i < Math.Max(baseLinesLength, diffLinesLength); ++i) { var line = new HtmlTableLine(); if (i < baseLinesLength) { line.Left = baseLines[i]; line.Left.LineText = baseFileInfo.Encoder.EncodeLine(baseLines[i].LineText, int.MaxValue, TabValue); lastBaseLine = line.Left.LineNum; } else { // new diff code - add entry for empty line with old line # var idx = i - baseLinesLength; line.Left = new Line { Id = lastBaseLine + '_' + idx }; } if (i < diffLinesLength) { line.Right = diffLines[i]; line.Right.LineText = diffFileInfo.Encoder.EncodeLine(diffLines[i].LineText, int.MaxValue, TabValue); lastDiffLine = line.Right.LineNum; } else { // new diff code - add entry for empty line with old line # var idx = i - diffLinesLength; line.Right = new Line { Id = lastDiffLine + '_' + idx }; } rowGroup.Lines.Add(line); } if (diffItem.DiffType == DiffType.Changed) { if (settings.diff.intraLineDiff) InterlineDiff(rowGroup, settings.diff.ignoreWhiteSpace); } rowGroups.Add(rowGroup); } baseEncoder.Dispose(); diffEncoder.Dispose(); var htmlLines = EncodeRowGroups(rowGroups, baseHeader, diffHeader, baseScriptIdPrefix, diffScriptIdPrefix, edgePrefix); if (!string.IsNullOrWhiteSpace(outputFile)) { var folder = Path.GetDirectoryName(outputFile); Directory.CreateDirectory(folder); File.WriteAllLines(outputFile, htmlLines); Log.Info("Generated {0}", outputFile); return outputFile; } else { return string.Join(Environment.NewLine, htmlLines); } }
public void GenDiffFiles(int id, string userName, UserSettingsDto settings, bool force = false) { var changeList = (from change in DataContext.ChangeLists where change.Id == id select change).FirstOrDefault(); if (changeList == null) { // Log return; } var baseReviewId = GetBaseReviewId(userName, changeList.Id); foreach (var changeFile in changeList.ChangeFiles) { var fileVersions = changeFile.FileVersions.ToArray(); if (fileVersions.Length == 1) { GenerateDiffFile(fileVersions[0], fileVersions[0], changeList.CL, baseReviewId, settings, force); continue; } var prev = 0; for (var idx = prev + 1; idx < fileVersions.Length; prev = idx++) { var vid1 = fileVersions[prev].Id; var vid2 = fileVersions[idx].Id; var versionQuery = from vr in DataContext.FileVersions where vr.Id == vid1 || vr.Id == vid2 select vr; if (versionQuery.Count() == 2) { var leftRight = versionQuery.ToArray(); FileVersion left, right; if (leftRight[0].Id == vid1) { left = leftRight[0]; right = leftRight[1]; } else { left = leftRight[1]; right = leftRight[0]; } GenerateDiffFile(left, right, changeList.CL, baseReviewId, settings, force); } } } }