root.node
[tfs.git] / tools / tf / DiffCommand.cs
blob6b5a6fc46d47d8d647b761524e587065990d2386
1 using System;
2 using System.IO;
3 using System.Collections;
4 using System.Collections.Generic;
5 using System.Text;
6 using Microsoft.TeamFoundation.Client;
7 using Microsoft.TeamFoundation.VersionControl.Common;
8 using Microsoft.TeamFoundation.VersionControl.Client;
9 using Mono.GetOptions;
11 [Command("difference", "Show pending changes, latest on server, a changeset, or local changes not pended as a unified diff.", "diff")]
12 class DifferenceCommand : Command
14 [Option("Output only whether files differ", "q", "brief")]
15 public bool OptionBrief = false;
17 [Option("Look for modified files", "", "modified")]
18 public bool OptionModified = false;
20 [Option("Show out of date files (newer version on server)", "", "old")]
21 public bool OptionOld = false;
23 [Option("Owner name", "O", "owner")]
24 public string OptionOwner;
26 public DifferenceCommand(Driver driver, string[] args): base(driver, args)
30 protected DiffOptions GetDiffOptions()
32 DiffOptions options = new DiffOptions();
33 options.UseThirdPartyTool = false;
34 options.Flags = DiffOptionFlags.EnablePreambleHandling;
35 options.OutputType = DiffOutputType.Unified;
36 options.TargetEncoding = Console.OutputEncoding;
37 options.SourceEncoding = Console.OutputEncoding;
38 options.StreamWriter = new StreamWriter(Console.OpenStandardOutput(),
39 Console.OutputEncoding);
40 options.StreamWriter.AutoFlush = true;
42 return options;
45 public void ShowModifiedFiles(Workspace workspace, string path)
47 char[] charsToTrim = { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar};
48 string itemPath = path.TrimEnd(charsToTrim);
50 workspace.RefreshMappings();
51 string serverPath = workspace.GetServerItemForLocalItem(itemPath);
53 // pull item list based on WorkspaceVersion. otherwise might get
54 // new items on server that haven't been pulled yet in the list returned
55 WorkspaceVersionSpec version = new WorkspaceVersionSpec(workspace);
57 // get item list from TFS server
58 ItemSpec itemSpec = new ItemSpec(itemPath, RecursionType.Full);
59 ItemSet itemSet = VersionControlServer.GetItems(itemSpec, version, DeletedState.NonDeleted, ItemType.Any, true);
60 Item[] items = itemSet.Items;
62 foreach (Item item in items)
64 if (item.ItemType != ItemType.File) continue;
65 if (item.ServerItem.Length == serverPath.Length) continue;
66 string serverItem = item.ServerItem.Remove(0, serverPath.Length+1);
68 // server item paths are separated with '/', but on windows the file list below has '\' separated paths
69 if (Path.DirectorySeparatorChar != '/')
70 serverItem = serverItem.Replace('/', Path.DirectorySeparatorChar);
72 // only looking for modifications, not deletes or adds
73 string fname = Path.Combine(itemPath, serverItem);
74 if (!File.Exists(fname)) continue;
75 if (FileAttributes.ReadOnly == (File.GetAttributes(fname) & FileAttributes.ReadOnly))
76 continue;
78 string p = fname.Substring(path.Length+1);
79 if (OptionBrief)
81 Console.WriteLine(CanonicalPath(p));
82 continue;
85 string tnameA = Path.GetTempFileName();
86 item.DownloadFile(tnameA);
87 IDiffItem a = new DiffItemLocalFile(tnameA, item.Encoding, DateTime.Now, false);
89 IDiffItem b = new DiffItemLocalFile(fname, item.Encoding, DateTime.Now, false);
91 Difference.DiffFiles(VersionControlServer, a, b,
92 GetDiffOptions(), p, true);
94 if (!String.IsNullOrEmpty(tnameA)) File.Delete(tnameA);
98 public void ShowOldFiles(Workspace workspace, string path)
100 // process command options
101 ItemSpec itemSpec = new ItemSpec(path, RecursionType.Full);
103 List<ItemSpec> itemSpecs = new List<ItemSpec>();
104 itemSpecs.Add(itemSpec);
106 ExtendedItem[][] items = workspace.GetExtendedItems(itemSpecs.ToArray(),
107 DeletedState.NonDeleted, ItemType.Any);
109 foreach (ExtendedItem[] itemArray in items)
111 foreach (ExtendedItem item in itemArray)
113 if (item.IsLatest) continue;
115 string p = item.LocalItem.Substring(path.Length);
116 if (OptionBrief)
118 Console.WriteLine(p);
119 continue;
122 IDiffItem a = new DiffItemNull();
123 IDiffItem b = new DiffItemNull();
125 if ((item.ChangeType & ChangeType.Add) != ChangeType.Add)
127 a = new DiffItemLocalFile(item.LocalItem, item.Encoding,
128 DateTime.Now, false);
131 if ((item.ChangeType & ChangeType.Delete) != ChangeType.Delete)
133 b = new DiffItemVersionedFile(VersionControlServer,
134 item.ItemId, item.VersionLatest, item.LocalItem);
137 Difference.DiffFiles(VersionControlServer, a, b,
138 GetDiffOptions(), p, true);
143 void ShowPendingChanges(Workspace workspace, string path)
145 PendingChange[] pendingChanges = workspace.GetPendingChanges(path, RecursionType.Full, true);
146 if (pendingChanges.Length == 0)
148 Console.WriteLine("No pending changes.");
149 Environment.Exit(0);
152 string cwd = Environment.CurrentDirectory;
153 foreach (PendingChange change in pendingChanges)
155 string p = change.LocalItem;
156 if (p.StartsWith(cwd)) p = p.Substring(cwd.Length+1);
158 if (OptionBrief)
160 Console.WriteLine(CanonicalPath(p));
161 continue;
164 IDiffItem a = new DiffItemNull();
165 IDiffItem b = new DiffItemNull();
167 string tname = null;
168 if (!change.IsAdd)
170 tname = Path.GetTempFileName();
171 change.DownloadBaseFile(tname);
173 a = new DiffItemLocalFile(tname, change.Encoding,
174 change.CreationDate, true);
177 if (!change.IsDelete)
179 b = new DiffItemLocalFile(change.LocalItem, change.Encoding,
180 change.CreationDate, false);
183 Difference.DiffFiles(VersionControlServer, a, b,
184 GetDiffOptions(), p, true);
186 if (!String.IsNullOrEmpty(tname))
187 File.Delete(tname);
191 public override void Run()
193 string path = Environment.CurrentDirectory;
194 if (Arguments.Length > 0)
196 path = Path.GetFullPath(Arguments[0]);
199 Workspace workspace = GetWorkspaceFromCache();
201 if (OptionOld)
203 ShowOldFiles(workspace, path);
204 Environment.Exit(0);
207 if (OptionModified)
209 ShowModifiedFiles(workspace, path);
210 Environment.Exit(0);
213 if (File.Exists(path) || Directory.Exists(path))
214 ShowPendingChanges(workspace, path);
215 else
217 VersionSpec versionSpec = VersionSpec.ParseSingleSpec(Arguments[0], OwnerFromString(OptionOwner));
218 if (versionSpec is ChangesetVersionSpec)
219 DiffHelper.ShowChangeset(VersionControlServer,
220 versionSpec as ChangesetVersionSpec,
221 OptionBrief, GetDiffOptions());