add.brief.option.add.gnome.vfs.binary.helper
[tfs.git] / class / Microsoft.TeamFoundation.VersionControl.Client / Difference.cs
blobec75910301c7e88e72dcbf34d8fa6eb6809587d1
1 //
2 // Microsoft.TeamFoundation.VersionControl.Client.Difference
3 //
4 // Authors:
5 // Joel Reed (joelwreed@gmail.com)
6 //
7 // Copyright (C) 2007 Joel Reed
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 using System;
30 using System.Collections;
31 using System.Collections.Generic;
32 using System.IO;
33 using System.Net;
34 using System.Text;
35 using Microsoft.TeamFoundation.VersionControl.Common;
37 namespace Microsoft.TeamFoundation.VersionControl.Client
39 public static class Difference
41 internal static readonly int CONTEXT = 3;
43 internal static void WriteHunkSet(StreamWriter stream,
44 string[] a, string[] b, List<Hunk> hunkSet)
46 if (hunkSet.Count == 0) return;
48 Hunk hunk1 = hunkSet[0];
49 DiffItem item1 = hunk1.Item;
51 int ctxStartA = Math.Max(item1.StartA - CONTEXT, -1);
52 int ctxStartB = Math.Max(item1.StartB - CONTEXT, -1);
54 int linesA = 0;
55 int linesB = 0;
57 foreach (Hunk hunk in hunkSet)
59 linesA += hunk.LinesA;
60 linesB += hunk.LinesB;
63 string header = String.Format("@@ -{0},{1} +",
64 ctxStartA+1, linesA);
66 header += String.Format("{0},", ctxStartB+1);
67 header += String.Format("{0} @@", linesB);
69 // header += String.Format("{0},{1},{2},{3}",
70 // item1.StartA, item1.deletedA, item1.StartB, item1.insertedB);
72 stream.WriteLine(header);
74 foreach (Hunk hunk in hunkSet)
76 stream.Write(hunk.ToString(a, b));
80 internal static void WriteUnified(StreamWriter stream,
81 string[] a, string[] b, DiffItem[] items)
83 List<Hunk> hunkSet = new List<Hunk>();
84 for (int x = 0; x < items.Length; x++)
86 DiffItem item = items[x];
88 int prevDist = CONTEXT;
89 if (x > 0) prevDist = Math.Min(CONTEXT, item.StartA - (items[x-1].StartA + items[x-1].deletedA));
91 int nextDist = CONTEXT;
92 if (x < items.Length - 1) nextDist = Math.Min(CONTEXT, items[x+1].StartA - item.StartA - 1);
94 Hunk hunk = new Hunk(item, prevDist, nextDist, a.Length, b.Length);
95 hunkSet.Add(hunk);
97 if (nextDist == CONTEXT)
99 WriteHunkSet(stream, a, b, hunkSet);
100 hunkSet.Clear();
104 WriteHunkSet(stream, a, b, hunkSet);
107 internal static void WriteNewFile(StreamWriter stream,
108 string[] b)
110 DiffItem item = new DiffItem();
111 item.StartA = 0; item.StartB = 0; item.deletedA = 0; item.insertedB = b.Length;
113 stream.WriteLine(String.Format("@@ -0,0 +1,{0} @@", b.Length));
114 Hunk hunk = new Hunk(item, 0, 0, 0, b.Length);
115 stream.Write(hunk.ToString(new string[0], b));
118 internal static void WriteHeader(DiffItemUtil aItem, DiffItemUtil bItem,
119 DiffOptions diffOpts)
121 StreamWriter stream = diffOpts.StreamWriter;
122 stream.Write("diff --tfs " + aItem.Name + " ");
123 if (!String.IsNullOrEmpty(diffOpts.SourceLabel))
124 stream.Write(diffOpts.SourceLabel + " ");
126 stream.Write(bItem.Name);
127 if (!String.IsNullOrEmpty(diffOpts.TargetLabel))
128 stream.Write("@" + diffOpts.TargetLabel);
130 stream.WriteLine();
132 // the trailing tabs below help diffutils grok filenames with spaces
133 stream.WriteLine("--- " + aItem.Name + "\t");
134 stream.WriteLine("+++ " + bItem.Name + "\t");
137 public static void DiffFiles (VersionControlServer versionControl,
138 IDiffItem source, IDiffItem target,
139 DiffOptions diffOpts, string fileNameForHeader,
140 bool wait)
142 DiffItemUtil aItem = new DiffItemUtil('a', fileNameForHeader, source.GetFile());
143 DiffItemUtil bItem = new DiffItemUtil('b', fileNameForHeader, target.GetFile());
144 StreamWriter stream = diffOpts.StreamWriter;
146 // short circuit for binary file comparisions
147 if (source.GetEncoding() == RepositoryConstants.EncodingBinary && target.GetEncoding() == RepositoryConstants.EncodingBinary)
149 stream.WriteLine("Binary files {0} and {1} differ", aItem.Name, bItem.Name);
150 return;
153 #if HAVE_GNOME_VFS
154 Gnome.Vfs.MimeType mimeType = new Gnome.Vfs.MimeType(Gnome.Vfs.Mime.TypeFromName(fileNameForHeader));
155 if (!mimeType.CanBeExecutable)
157 stream.WriteLine("Binary files {0} and {1} differ", aItem.Name, bItem.Name);
158 return;
160 #endif
162 WriteHeader(aItem, bItem, diffOpts);
164 // short circuit new files
165 if (aItem.Length == 0)
167 WriteNewFile(stream, bItem.Lines);
168 return;
171 Hashtable hashtable = new Hashtable(aItem.Length + bItem.Length);
172 bool ignoreWhiteSpace = (diffOpts.Flags & DiffOptionFlags.IgnoreWhiteSpace) == DiffOptionFlags.IgnoreWhiteSpace;
174 DiffItem[] items = DiffUtil.DiffText(hashtable, aItem.Lines, bItem.Lines,
175 ignoreWhiteSpace, ignoreWhiteSpace, false);
177 WriteUnified(stream, aItem.Lines, bItem.Lines, items);