give command only its args not all args
[tfs.git] / tools / tf / OnlineCommand.cs
blob6289be1ae92540b142c71458ae057567291bb973
1 //
2 // OnlineCommand.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.Security.Cryptography;
31 using System.Collections.Generic;
32 using System.IO;
33 using System.Text;
34 using System.Text.RegularExpressions;
35 using Microsoft.TeamFoundation.Client;
36 using Microsoft.TeamFoundation.VersionControl.Common;
37 using Microsoft.TeamFoundation.VersionControl.Client;
39 [Command("online", "Finds all writable files and marks them as pending changes on the server.")]
40 class OnlineCommand : Command
42 public OnlineCommand(Driver driver, string[] args): base(driver, args)
46 public override void Run()
48 string path = Environment.CurrentDirectory;
49 if (Arguments.Length > 1)
51 path = Path.GetFullPath(Arguments[1]);
54 char[] charsToTrim = { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar};
55 string itemPath = path.TrimEnd(charsToTrim);
57 Workspace workspace = GetWorkspaceFromCache();
58 workspace.RefreshMappings();
59 string serverPath = workspace.GetServerItemForLocalItem(itemPath);
61 // pull item list based on WorkspaceVersion. otherwise might get
62 // new items on server that haven't been pulled yet in the list returned
63 WorkspaceVersionSpec version = new WorkspaceVersionSpec(workspace);
65 // process recursion settings
66 RecursionType rtype = Options.Recursive ? RecursionType.Full : RecursionType.OneLevel;
67 bool recursionSetting = Settings.Current.GetAsBool("Online.Recursive");
68 if (recursionSetting) rtype = RecursionType.Full;
69 SearchOption searchType = (rtype == RecursionType.Full) ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
71 // process command options
72 ItemSpec itemSpec = new ItemSpec(itemPath, rtype);
73 ItemSet itemSet = VersionControlServer.GetItems(itemSpec, version, DeletedState.NonDeleted, ItemType.Any, true);
75 // get item list from TFS server
76 Item[] items = itemSet.Items;
77 SortedList<string, byte[] > itemList = new SortedList<string, byte[] >(PathComparer);
78 MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
80 foreach (Item item in items)
82 if (item.ServerItem.Length == serverPath.Length) continue;
83 string serverItem = item.ServerItem.Remove(0, serverPath.Length+1);
85 // server item paths are separated with '/', but on windows the file list below has '\' separated paths
86 if (Path.DirectorySeparatorChar != '/')
87 serverItem = serverItem.Replace('/', Path.DirectorySeparatorChar);
89 string fname = Path.Combine(itemPath, serverItem);
90 //Console.WriteLine(serverItem + " : " + fname);
92 itemList.Add(fname, item.HashValue);
95 DirectoryInfo dir = new DirectoryInfo(path);
96 FileInfo[] localFiles = dir.GetFiles("*", searchType);
98 SortedList<string, bool> dirList = new SortedList<string, bool>();
99 List<string> addedFiles = new List<string>();
100 List<string> editedFiles = new List<string>();
101 List<string> deletedFiles = new List<string>();
103 // should we ignore/exclude any thing?
104 Regex excludes = WildcardToRegex(Settings.Current.Get("File.Excludes"));
106 // by default, if nothing specified we process all changes
107 if ((!Options.Modified) && (!Options.Deleted) && (!Options.Added))
109 Options.Modified = Options.Added = Options.Deleted = true;
112 foreach (FileInfo file in localFiles)
114 // skip files we're not interested in
115 if (excludes.IsMatch(file.Name)) continue;
117 dirList.Add(file.FullName, true);
118 bool isReadOnly = (FileAttributes.ReadOnly == (File.GetAttributes(file.FullName) & FileAttributes.ReadOnly));
120 if (!itemList.ContainsKey(file.FullName))
122 if (Options.Added)
124 Console.WriteLine("Added: " + file.FullName);
125 addedFiles.Add(file.FullName);
128 else if (!isReadOnly && Options.Modified)
130 // now check file hashes
131 string itemHash = Convert.ToBase64String(itemList[file.FullName]);
132 using (FileStream fileStream = new FileStream(file.FullName, FileMode.Open, FileAccess.Read))
134 md5.ComputeHash(fileStream);
135 string localHash = Convert.ToBase64String(md5.Hash);
136 if (itemHash != localHash)
138 editedFiles.Add(file.FullName);
139 Console.WriteLine("Modified: " + file.FullName);
145 foreach (DirectoryInfo di in dir.GetDirectories("*", SearchOption.AllDirectories))
147 dirList.Add(di.FullName, true);
150 if (Options.Deleted)
152 foreach (string key in itemList.Keys)
154 // skip files that exist or we're not interested in
155 if (dirList.ContainsKey(key)) continue;
156 if (excludes.IsMatch(key)) continue;
158 Console.WriteLine("Deleted: " + key);
159 deletedFiles.Add(key);
163 if (Options.Preview) return;
165 int changes = 0;
166 changes += workspace.PendAdd(addedFiles.ToArray(), false);
167 changes += workspace.PendEdit(editedFiles.ToArray(), RecursionType.None);
168 changes += workspace.PendDelete(deletedFiles.ToArray(), RecursionType.None);
169 Console.WriteLine("{0} pending changes.", changes);