/// <summary> /// Saves the text of a file version to a temp file. /// </summary> /// <param name="version"> The version to save. </param> /// <returns> The name of the file, or null if it fails. </returns> private TempFile SaveToTempFile(FileVersion version, bool ignoreBase = false) { var reader = GetFileStream(version, ignoreBase); if (reader == null) return null; var file = new TempFile(); using (reader) using (var writer = new StreamWriter(file.FullName)) { foreach (var line in reader.ReadLines()) writer.WriteLine(line); } // We created the temp file, but because of the security settings for %TEMP% might not have access to it. // Grant it explicitly. AddFileSecurity(file.FullName, WellKnownSidType.AuthenticatedUserSid, FileSystemRights.Read, AccessControlType.Allow); AddFileSecurity(file.FullName, WellKnownSidType.CreatorOwnerSid, FileSystemRights.FullControl, AccessControlType.Allow); return file; }
/// <summary> /// Computes the displayed name of the file version. Similar to ComputeMoniker, but without the action. /// </summary> /// <param name="name"> The base name of a file (excluding the path). </param> /// <param name="version"> The version. </param> /// <returns> The string to display. </returns> private static string FileDisplayName(string name, FileVersion version) { StringBuilder sb = new StringBuilder(); sb.Append(name); sb.Append('#'); sb.Append(version.Revision.ToString()); if (!version.IsRevisionBase && version.TimeStamp != null) sb.Append(" " + version.TimeStamp); return sb.ToString(); }
/// <summary> /// Produces a stream for a file version. This may involve reading the database for the base for the version, /// if the version is a diff. /// </summary> /// <param name="version"> The version to stream. </param> /// <returns> The resultant full-text stream. </returns> private StreamCombiner GetFileStream(FileVersion version, bool ignoreBase = false) { if (version.IsFullText) return new StreamCombiner(version.Text); var baseVersionQuery = from fl in DataContext.FileVersions where fl.FileId == version.FileId && fl.Revision == version.Revision && fl.IsRevisionBase select fl; if (baseVersionQuery.Count() != 1) { if (ignoreBase) return new StreamCombiner(version.Text); throw new Exception("Base revision not found. This can happen if the file changed type from binary to text " + "as part of this change. If this is not the case, it might be a bug - report it!"); } var baseVersion = baseVersionQuery.Single(); return new StreamCombiner(baseVersion.Text, version.Text); }
public void GenerateDiffInfoFile(string clName, FileVersion left, FileVersion right, int baseReviewId) { var js = new JavaScriptSerializer(); var jsonFile = string.Format(@"{0}\{1}\{2}\{3}.{4}.json", _diffFolderRoot, clName, left.FileId, left.Id, right.Id); var json = JsonConvert.SerializeObject(new DiffFileDto(left, right, clName, baseReviewId), Formatting.Indented); File.WriteAllText(jsonFile, json); }
/// <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; } } }
public FileVersionDto(FileVersion input, bool complete) { if (input == null) return; this.action = input.Action; this.fileId = input.FileId; this.id = input.Id; this.isFullText = input.IsFullText; this.isRevisionBase = input.IsRevisionBase; this.isText = input.IsText; this.revision = input.Revision; this.reviewRevision = input.ReviewRevision; this.timeStamp = input.TimeStamp; this.name = string.Format("{0}_{1}", System.IO.Path.GetFileName(input.ChangeFile.ServerFileName), input.Id); if (complete) { changeFile = new ChangeFileDto(input.ChangeFile, false); } }
public DiffFileDto(FileVersion left, FileVersion right, string CL, int baseReviewId) { this.left = new FileVersionDto(left, false); this.right = new FileVersionDto(right, false); this.CL = CL; this.baseReviewId = baseReviewId; }