show the difference between two versions for a specified path
[tfs.git] / tools / opentf / RollbackCommand.cs
blob016fd88970b4a839bfae8f24ad76c124ded35397
1 //
2 // RollbackCommand.cs
3 //
4 // Authors:
5 // Joel Reed (joelwreed@gmail.com)
6 //
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.Generic;
31 using System.IO;
32 using System.Text;
33 using Microsoft.TeamFoundation.Client;
34 using Microsoft.TeamFoundation.VersionControl.Client;
35 using Mono.GetOptions;
37 [Command("rollback", "Undo a changeset (Warning: Completely ignores any subsequent changes made after the specified changeset!)", "<changeset id>")]
38 class RollbackCommand : Command
40 [Option("Preview", "", "preview")]
41 public bool OptionPreview = false;
43 private List<string> addedFiles = new List<string>();
44 private List<string> editedFiles = new List<string>();
45 private List<string> deletedFiles = new List<string>();
46 private Workspace workspace;
47 private int changeCount = 0;
49 public RollbackCommand(Driver driver, string[] args): base(driver, args)
53 public void ProcessEdits(Changeset changeset, int[] ids, int cid)
55 if (ids.Length == 0) return;
57 // find items in prior changeset
58 Item[] items = VersionControlServer.GetItems(ids, cid-1, true);
59 SortedList<int, Item> itemList = new SortedList<int, Item>();
60 foreach (Item item in items)
62 // itemId of 0 means a null item, IOW file was added in this changeset
63 // and missing in prior changeset
64 if (item.ItemId == 0) continue;
65 itemList.Add(item.ItemId, item);
68 // fetch all items in one fell swoop
69 List<string> directoryRenames = new List<string>();
70 foreach (Change change in changeset.Changes)
72 if ((change.ChangeType & ChangeType.Add) == ChangeType.Add) continue;
74 if (! itemList.ContainsKey(change.Item.ItemId))
76 Console.WriteLine("Cannot undo " + ChangeTypeToString(change.ChangeType) + ": " + change.Item.ServerItem);
77 continue;
80 Item previousItem = itemList[change.Item.ItemId];
81 string localItem = workspace.GetLocalItemForServerItem(previousItem.ServerItem);
83 if ((change.ChangeType & ChangeType.Rename) == ChangeType.Rename)
85 bool fnd = false;
86 foreach (string directory in directoryRenames)
88 if (localItem.StartsWith(directory))
90 fnd = true;
91 break;
95 // skip file renames when we've already renamed the directory
96 if (fnd) continue;
98 string newItem = workspace.GetLocalItemForServerItem(change.Item.ServerItem);
99 Console.WriteLine("Undo rename: " + localItem + " -> " + newItem);
101 if (!OptionPreview)
103 workspace.PendRename(newItem, localItem);
104 changeCount += 1;
107 if (change.Item.ItemType == ItemType.Folder)
108 directoryRenames.Add(localItem);
110 continue;
113 Console.WriteLine("Undo " + ChangeTypeToString(change.ChangeType) + ": " + change.Item.ServerItem);
115 previousItem.DownloadFile(localItem);
117 if ((change.ChangeType & ChangeType.Delete) == ChangeType.Delete)
118 addedFiles.Add(localItem);
119 else
120 editedFiles.Add(localItem);
124 public override void Run()
126 workspace = GetWorkspaceFromCache();
127 workspace.RefreshMappings();
129 if (Arguments.Length < 1)
131 Console.WriteLine("No changeset specified.");
132 Environment.Exit((int)ExitCode.Failure);
135 int cid = Convert.ToInt32(Arguments[0]);
136 Changeset changeset = VersionControlServer.GetChangeset(cid, true, false);
138 // fetch all items in one fell swoop
139 List<int> ids = new List<int>();
140 foreach (Change change in changeset.Changes)
142 if ((change.ChangeType & ChangeType.Add) == ChangeType.Add)
144 if (change.Item.ItemType != ItemType.Folder)
146 string localItem = workspace.GetLocalItemForServerItem(change.Item.ServerItem);
147 Console.WriteLine("Undo add: " + change.Item.ServerItem);
148 deletedFiles.Add(localItem);
151 continue;
154 ids.Add(change.Item.ItemId);
157 ProcessEdits(changeset, ids.ToArray(), cid);
159 if (OptionPreview) return;
161 changeCount += workspace.PendAdd(addedFiles.ToArray(), false);
162 changeCount += workspace.PendEdit(editedFiles.ToArray(), RecursionType.None);
163 changeCount += workspace.PendDelete(deletedFiles.ToArray(), RecursionType.None);
164 Console.WriteLine("{0} pending changes.", changeCount);