void ShowPendingChanges(Workspace workspace, string[] paths) { PendingChange[] pendingChanges = workspace.GetPendingChanges(paths, RecursionType.Full, true); if (pendingChanges.Length == 0) { Console.WriteLine("No pending changes."); Environment.Exit((int)ExitCode.PartialSuccess); } string cwd = Environment.CurrentDirectory; foreach (PendingChange change in pendingChanges) { string p = change.LocalItem; if (p.StartsWith(cwd)) { p = p.Substring(cwd.Length + 1); } if (OptionBrief) { Driver.WriteLine(CanonicalPath(p)); continue; } IDiffItem a = new DiffItemNull(); IDiffItem b = new DiffItemNull(); string tname = null; if (!change.IsAdd) { tname = Path.GetTempFileName(); change.DownloadBaseFile(tname); a = new DiffItemLocalFile(tname, change.Encoding, change.CreationDate, true); } if (!change.IsDelete) { b = new DiffItemLocalFile(change.LocalItem, change.Encoding, change.CreationDate, false); } Difference.DiffFiles(VersionControlServer, a, b, GetDiffOptions(), p, true); if (!String.IsNullOrEmpty(tname)) { File.Delete(tname); } } }
public void ShowOldFiles(Workspace workspace, string path) { // process command options ItemSpec itemSpec = new ItemSpec(path, RecursionType.Full); List <ItemSpec> itemSpecs = new List <ItemSpec>(); itemSpecs.Add(itemSpec); ExtendedItem[][] items = workspace.GetExtendedItems(itemSpecs.ToArray(), DeletedState.NonDeleted, ItemType.Any); foreach (ExtendedItem[] itemArray in items) { foreach (ExtendedItem item in itemArray) { if (item.IsLatest) { continue; } string p = item.LocalItem.Substring(path.Length); if (OptionBrief) { Driver.WriteLine(p); continue; } IDiffItem a = new DiffItemNull(); IDiffItem b = new DiffItemNull(); if ((item.ChangeType & ChangeType.Add) != ChangeType.Add) { a = new DiffItemLocalFile(item.LocalItem, item.Encoding, DateTime.Now, false); } if ((item.ChangeType & ChangeType.Delete) != ChangeType.Delete) { b = new DiffItemVersionedFile(VersionControlServer, item.ItemId, item.VersionLatest, item.LocalItem); } Difference.DiffFiles(VersionControlServer, a, b, GetDiffOptions(), p, true); } } }
/// <summary> /// Generates a report about Edit change /// </summary> private void GenerateEditReport(string diffFileName, Changeset changeset, Change change) { IDiffItem origItem = new DiffItemVersionedFile(_sourceControl, change.Item.ServerItem, new ChangesetVersionSpec(changeset.ChangesetId - 1)); IDiffItem newItem = new DiffItemVersionedFile(_sourceControl, change.Item.ServerItem, new ChangesetVersionSpec(changeset.ChangesetId)); using (var writer = new StreamWriter(diffFileName)) { WriteHeader(writer, changeset); var diffOptions = new DiffOptions { UseThirdPartyTool = false, OutputType = DiffOutputType.Context, ContextLines = 0, StreamWriter = writer }; Difference.DiffFiles(_sourceControl, origItem, newItem, diffOptions, null, true); } }
public static DiffSummary DiffFiles(String source, Int32 sourceCodePage, String target, Int32 targetCodePage, DiffOptions diffOptions) { DiffSegment currSegment = Difference.DiffFiles(source, sourceCodePage, target, targetCodePage, diffOptions); DiffSummary summary = new DiffSummary(); // Initialize a set of position markers which will be used to walk // through the files Int32 currentOriginalPosition = 0; Int32 currentModifiedPosition = 0; while (currSegment != null) { // Everything between the postiion markers and the start of the current common segment // will be either lines which were deleted or lines which were added Int32 linesDeleted = currSegment.OriginalStart - currentOriginalPosition; Int32 linesAdded = currSegment.ModifiedStart - currentModifiedPosition; summary.TotalLinesModified += Math.Min(linesDeleted, linesAdded); summary.TotalLinesAdded += Math.Max(0, linesAdded - linesDeleted); summary.TotalLinesDeleted += Math.Max(0, linesDeleted - linesAdded); // Advance the position markers to the end of the common section currentOriginalPosition = currSegment.OriginalStart + currSegment.OriginalLength; currentModifiedPosition = currSegment.ModifiedStart + currSegment.ModifiedLength; // Move to the next segment in the linked-list currSegment = currSegment.Next; } // After walking the linked-list of common sections, the position markers // will be pointing to the end of the file, thus we can infer how many lines // are in each file. summary.OriginalLineCount = currentOriginalPosition; summary.ModifiedLineCount = currentModifiedPosition; return(summary); }
// Display the differences between the two file versions. static void DiffFiles(Item item1, Item item2) { if (item1.ItemType != ItemType.File) { return; } Console.WriteLine(); DiffItemVersionedFile diffItem1 = new DiffItemVersionedFile(item1, new ChangesetVersionSpec(item1.ChangesetId)); DiffItemVersionedFile diffItem2 = new DiffItemVersionedFile(item2, new ChangesetVersionSpec(item2.ChangesetId)); // Here we set up the options to show the diffs in the console with the unified diff // format. // If you simply want to launch the external diff viewer, rather than get a text diff, // you just need to set UseThirdPartyTool to true. You don't need to set any of the // other properties to use the external tool. DiffOptions options = new DiffOptions(); options.UseThirdPartyTool = false; // These settings are just for the text diff (not needed for an external tool). options.Flags = DiffOptionFlags.EnablePreambleHandling | DiffOptionFlags.IgnoreWhiteSpace; options.OutputType = DiffOutputType.Unified; options.TargetEncoding = Console.OutputEncoding; options.SourceEncoding = Console.OutputEncoding; options.StreamWriter = new StreamWriter(Console.OpenStandardOutput(), Console.OutputEncoding); options.StreamWriter.AutoFlush = true; // The last parameter indicates whether the code should block until the external diff // viewer exits. Set it to false if you are calling this from a GUI app. Difference.DiffFiles(item1.VersionControlServer, diffItem1, diffItem2, options, item1.ServerItem, true); }
static public void ShowChangeset(VersionControlServer vcs, ChangesetVersionSpec versionSpec, bool brief, DiffOptions diffOpts) { int changesetId = versionSpec.ChangesetId; Changeset changeset = vcs.GetChangeset(changesetId, true, true); // fetch all items in one fell swoop List <int> ids = new List <int>(); foreach (Change change in changeset.Changes) { ids.Add(change.Item.ItemId); } // find items in prior changeset Item[] items = vcs.GetItems(ids.ToArray(), changesetId - 1, true); SortedList <int, Item> itemList = new SortedList <int, Item>(); foreach (Item item in items) { // itemId of 0 means a null item, IOW file was added in this changeset // and missing in prior changeset if (item.ItemId == 0) { continue; } itemList.Add(item.ItemId, item); } foreach (Change change in changeset.Changes) { // skip folders if (change.Item.ItemType == ItemType.Folder) { continue; } string p = change.Item.ServerItem.Substring(2); if (brief) { Console.WriteLine(p); continue; } IDiffItem a = new DiffItemNull(); IDiffItem b = new DiffItemNull(); string tnameA = null; string tnameB = null; if (((change.ChangeType & ChangeType.Add) != ChangeType.Add) && (itemList.ContainsKey(change.Item.ItemId))) { Item itemA = itemList[change.Item.ItemId]; tnameA = Path.GetTempFileName(); itemA.DownloadFile(tnameA); a = new DiffItemLocalFile(tnameA, itemA.Encoding, changeset.CreationDate, true); } if ((change.ChangeType & ChangeType.Delete) != ChangeType.Delete) { tnameB = Path.GetTempFileName(); change.Item.DownloadFile(tnameB); b = new DiffItemLocalFile(tnameB, change.Item.Encoding, changeset.CreationDate, true); } diffOpts.TargetLabel = versionSpec.DisplayString; Difference.DiffFiles(vcs, a, b, diffOpts, p, true); if (!String.IsNullOrEmpty(tnameA)) { File.Delete(tnameA); } if (!String.IsNullOrEmpty(tnameB)) { File.Delete(tnameB); } } }
public IAnnotatedFile Annotate(string path, VersionSpec version) { var options = new DiffOptions { Flags = DiffOptionFlags.EnablePreambleHandling | DiffOptionFlags.IgnoreLeadingAndTrailingWhiteSpace | DiffOptionFlags.IgnoreEndOfLineDifference }; PendingChange[] pendingChanges = server.GetWorkspace(path).GetPendingChanges(path); if (pendingChanges.Length >= 2) { throw new InvalidOperationException("Expected at most 1 pending change, but got " + pendingChanges.Length); } Changeset currentChangeset = null; AnnotatedFile annotatedFile; string currentPath; int currentEncoding; if (pendingChanges.Length == 1 && (pendingChanges[0].ChangeType & ChangeType.Edit) != 0) { annotatedFile = new AnnotatedFile(path, pendingChanges[0].Encoding); if (annotatedFile.IsBinary()) { return(annotatedFile); } currentPath = path; currentEncoding = pendingChanges[0].Encoding; } else { annotatedFile = null; currentPath = null; currentEncoding = 0; } using (var historyProvider = new HistoryProvider(server, path, version)) { var done = false; while (!done && historyProvider.Next()) { Changeset previousChangeset = historyProvider.Changeset(); string previousPath = historyProvider.Filename(); int previousEncoding = previousChangeset.Changes[0].Item.Encoding; if (annotatedFile == null) { annotatedFile = new AnnotatedFile(previousPath, previousEncoding); if (annotatedFile.IsBinary()) { return(annotatedFile); } } else if (previousEncoding == -1) { annotatedFile.Apply(currentChangeset); done = true; } else { var diff = Diff(Difference.DiffFiles(currentPath, currentEncoding, previousPath, previousEncoding, options)); done = annotatedFile.ApplyDiff(currentChangeset, diff); } currentChangeset = previousChangeset; currentEncoding = previousEncoding; currentPath = previousPath; } if (annotatedFile != null) { annotatedFile.Apply(currentChangeset); } } return(annotatedFile); }
/// <summary> /// Create a difference string from a shelveset /// Also sets the URl to the file on the TFS Server /// </summary> /// <param name="set">The selected PendingSet</param> /// <returns>the diff String which is sent to Codestriker</returns> public string ReviewShelveset( PendingSet set) { if (set == null) { throw new ArgumentNullException(nameof(set)); } MemoryStream stream = new MemoryStream(); StreamWriter writer = new StreamWriter(stream); { DiffOptions options = new DiffOptions { Flags = DiffOptionFlags.EnablePreambleHandling, OutputType = DiffOutputType.Unified, TargetEncoding = Encoding.UTF8, SourceEncoding = Encoding.UTF8, Recursive = true, StreamWriter = writer }; StringBuilder sb = new StringBuilder(); int streampos = 0; foreach (var pendingchange in set.PendingChanges) { if (pendingchange.ItemType != ItemType.Folder) { string fileUrl = string.Format(pendingchange.VersionControlServer.TeamProjectCollection.Uri.AbsoluteUri); fileUrl += s_LinkCompletionVersioncontrol; fileUrl += $"{HttpUtility.UrlEncode(pendingchange.PendingSetName + ";" + pendingchange.PendingSetOwner)}{s_PathParameter}"; fileUrl += HttpUtility.UrlEncode(pendingchange.LocalOrServerItem); //the semicolons after s_ActionParameter and pendingchange.FileName are important for the right parsing on codestriker fileUrl += $"{s_ActionParameter}&#path={HttpUtility.UrlEncode(pendingchange.LocalOrServerItem)}{s_ActionParameter};{pendingchange.LocalOrServerItem};"; var diffChange = new DiffItemShelvedChange(set.Name, pendingchange); var diffVersion = Difference.CreateTargetDiffItem(m_VersionControl, pendingchange, null); Difference.DiffFiles( m_VersionControl, diffVersion, diffChange, options, string.Empty, true); writer.Flush(); sb.Append(writer.GetHashCode()).Append(Environment.NewLine); string pendingChangeString = Encoding.UTF8.GetString(stream.ToArray().Skip(streampos).ToArray()); Regex rgx = new Regex(s_RegexPattern); //replace the filename with the tfs url path of the file //necessary for the link between codestriker and TFS pendingChangeString = rgx.Replace( pendingChangeString, m => m.Groups["prefix"].Value + ": " + fileUrl, 1); sb.Append(pendingChangeString); streampos = stream.ToArray().Length; } } return(sb.ToString()); } #endregion }
public IAnnotatedFile Annotate(string path, VersionSpec version) { var options = new DiffOptions(); options.Flags = DiffOptionFlags.EnablePreambleHandling; PendingChange[] pendingChanges = server.GetWorkspace(path).GetPendingChanges(path); if (pendingChanges.Length >= 2) { throw new InvalidOperationException("Expected at most 1 pending change, but got " + pendingChanges.Length); } Changeset currentChangeset = null; AnnotatedFile annotatedFile; string currentPath; int currentEncoding; if (pendingChanges.Length == 1 && (pendingChanges[0].ChangeType & ChangeType.Edit) != 0) { annotatedFile = new AnnotatedFile(path, pendingChanges[0].Encoding); if (annotatedFile.IsBinary()) { return(annotatedFile); } currentPath = path; currentEncoding = pendingChanges[0].Encoding; } else { annotatedFile = null; currentPath = null; currentEncoding = 0; } var history = server.QueryHistory(path, version, 0, RecursionType.None, null, null, version, int.MaxValue, true, false, true, false); using (var historyProvider = new HistoryProvider(server, (IEnumerable <Changeset>)history)) { bool done = false; while (!done && historyProvider.Next()) { Changeset previousChangeset = historyProvider.Changeset(); string previousPath = historyProvider.Filename(); int previousEncoding = previousChangeset.Changes[0].Item.Encoding; if (annotatedFile == null) { annotatedFile = new AnnotatedFile(previousPath, previousEncoding); if (annotatedFile.IsBinary()) { return(annotatedFile); } } else if (previousEncoding == -1) { annotatedFile.Apply(currentChangeset); done = true; } else { var diff = Diff(Difference.DiffFiles(currentPath, currentEncoding, previousPath, previousEncoding, options)); done = annotatedFile.ApplyDiff(currentChangeset, diff); } currentChangeset = previousChangeset; currentEncoding = previousEncoding; currentPath = previousPath; } if (annotatedFile != null) { annotatedFile.Apply(currentChangeset); } } return(annotatedFile); }
public void ShowModifiedFiles(Workspace workspace, string path) { char[] charsToTrim = { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }; string itemPath = path.TrimEnd(charsToTrim); workspace.RefreshMappings(); string serverPath = workspace.GetServerItemForLocalItem(itemPath); // pull item list based on WorkspaceVersion. otherwise might get // new items on server that haven't been pulled yet in the list returned WorkspaceVersionSpec version = new WorkspaceVersionSpec(workspace); // get item list from TFS server ItemSpec itemSpec = new ItemSpec(itemPath, RecursionType.Full); ItemSet itemSet = VersionControlServer.GetItems(itemSpec, version, DeletedState.NonDeleted, ItemType.Any, true); Item[] items = itemSet.Items; foreach (Item item in items) { if (item.ItemType != ItemType.File) { continue; } if (item.ServerItem.Length == serverPath.Length) { continue; } string serverItem = item.ServerItem.Remove(0, serverPath.Length + 1); // server item paths are separated with '/', but on windows the file list below has '\' separated paths if (Path.DirectorySeparatorChar != '/') { serverItem = serverItem.Replace('/', Path.DirectorySeparatorChar); } // only looking for modifications, not deletes or adds string fname = Path.Combine(itemPath, serverItem); if (!File.Exists(fname)) { continue; } if (FileAttributes.ReadOnly == (File.GetAttributes(fname) & FileAttributes.ReadOnly)) { continue; } using (FileStream fileStream = new FileStream(fname, FileMode.Open, FileAccess.Read)) { string localHash = Convert.ToBase64String(md5.ComputeHash(fileStream)); string itemHash = Convert.ToBase64String(item.HashValue); if (itemHash == localHash) { continue; } } string p = fname.Substring(path.Length + 1); if (OptionBrief) { Driver.WriteLine(CanonicalPath(p)); continue; } string tnameA = Path.GetTempFileName(); item.DownloadFile(tnameA); IDiffItem a = new DiffItemLocalFile(tnameA, item.Encoding, DateTime.Now, false); IDiffItem b = new DiffItemLocalFile(fname, item.Encoding, DateTime.Now, false); Difference.DiffFiles(VersionControlServer, a, b, GetDiffOptions(), p, true); if (!String.IsNullOrEmpty(tnameA)) { File.Delete(tnameA); } } }