5 // Joel Reed (joelwreed@gmail.com)
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:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
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.
30 using System
.Collections
.Generic
;
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
);
80 Item previousItem
= itemList
[change
.Item
.ItemId
];
81 string localItem
= workspace
.GetLocalItemForServerItem(previousItem
.ServerItem
);
83 if ((change
.ChangeType
& ChangeType
.Rename
) == ChangeType
.Rename
)
86 foreach (string directory
in directoryRenames
)
88 if (localItem
.StartsWith(directory
))
95 // skip file renames when we've already renamed the directory
98 string newItem
= workspace
.GetLocalItemForServerItem(change
.Item
.ServerItem
);
99 Console
.WriteLine("Undo rename: " + localItem
+ " -> " + newItem
);
103 workspace
.PendRename(newItem
, localItem
);
107 if (change
.Item
.ItemType
== ItemType
.Folder
)
108 directoryRenames
.Add(localItem
);
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
);
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
);
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
);