BUGFIX: tf online <path> shouldn't croak if <path> is an add awaiting
[tfs.git] / tools / opentf / Command.cs
blob0f254889ce38ec5c10356fb918f2c65a673e9eac
1 //
2 // Command.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.IO;
31 using System.Text;
32 using System.Text.RegularExpressions;
33 using System.Collections.Generic;
34 using Microsoft.TeamFoundation.Client;
35 using Microsoft.TeamFoundation.VersionControl.Client;
36 using Microsoft.TeamFoundation.VersionControl.Common;
38 abstract class Command : CommandOptions
40 private static bool runningOnUnix = true;
41 private string[] arguments;
42 private Driver driver;
43 private static Regex fileExcludes;
44 private static Regex dirExcludes;
46 public Driver Driver
48 get { return driver; }
51 public string[] Arguments
53 get { return arguments; }
56 static Command()
58 int p = (int) Environment.OSVersion.Platform;
59 if (!((p == 4) || (p == 128))) runningOnUnix = false;
61 ReadFileExcludes();
64 public static StringComparer PathComparer
66 get {
67 if (!runningOnUnix) return StringComparer.CurrentCultureIgnoreCase;
68 return StringComparer.CurrentCulture;
72 public Command(Driver driver, string[] args)
74 this.driver = driver;
75 ProcessArgs(args);
76 this.arguments = RemainingArguments;
79 public Workspace GetWorkspaceFromServer()
81 string name = OptionWorkspace;
83 // if option passed use it
84 if (String.IsNullOrEmpty(name))
86 // guess based on current working directory
87 WorkspaceInfo info = Workstation.Current.GetLocalWorkspaceInfo(Environment.CurrentDirectory);
88 if (info != null) name = info.Name;
91 if (String.IsNullOrEmpty(name))
92 name = Settings.Current.Get("Workspace.Default");
94 if (String.IsNullOrEmpty(name))
96 Console.WriteLine("Unable to determine the workspace");
97 Console.WriteLine(" hint: try adding /workspace:<name>");
98 Environment.Exit((int)ExitCode.Failure);
101 return VersionControlServer.GetWorkspace(name, Driver.Username);
104 public WorkspaceInfo GetWorkspaceInfoFromCache()
106 string path = Environment.CurrentDirectory;
107 if (Arguments.Length > 0)
109 path = Path.GetFullPath(Arguments[0]);
112 WorkspaceInfo info = Workstation.Current.GetLocalWorkspaceInfo(path);
113 if (info != null) return info;
115 if (String.IsNullOrEmpty(OptionWorkspace))
117 Console.WriteLine("Unable to determine the workspace.");
118 Console.WriteLine(" Path: " + path);
119 return null;
122 string ownerName = String.Format("{0}\\{1}", Driver.Domain, Driver.Username).ToUpper();
123 info = Workstation.Current.GetLocalWorkspaceInfo(Driver.VersionControlServer,
124 OptionWorkspace, ownerName);
126 if (info == null)
128 Console.WriteLine("Unable to determine the workspace.");
129 Console.WriteLine(" Workspace Option: " + OptionWorkspace);
132 return info;
135 public Workspace GetWorkspaceFromCache()
137 WorkspaceInfo info = GetWorkspaceInfoFromCache();
139 if (info == null)
141 Console.WriteLine();
142 Console.WriteLine("Hints:");
143 Console.WriteLine(" Try adding /workspace:<name>");
144 Console.WriteLine(" Review command options prefixed with '/'. Invalid options are mistaken for paths.");
145 Environment.Exit((int)ExitCode.Failure);
148 return VersionControlServer.GetWorkspace(info);
151 public VersionSpec VersionFromString(string version)
153 if (!String.IsNullOrEmpty(version))
154 return VersionSpec.ParseSingleSpec(version, Driver.Username);
155 else
156 return VersionSpec.Latest;
159 static public string ChangeTypeToString(ChangeType change)
161 string ctype = "edit";
163 if ((change & ChangeType.Add) == ChangeType.Add) ctype = "add";
164 else if ((change & ChangeType.Delete) == ChangeType.Delete) ctype = "delete";
166 return ctype;
169 public int WindowWidth
171 get {
172 // if output piped to a file, we don't want 0!
173 // this also throws on weird terminals on msclr
176 int w = Console.WindowWidth;
177 if (w != 0) return w - 1;
179 catch (IOException) {}
180 return 143;
184 public string OwnerFromString(string owner)
186 if (String.IsNullOrEmpty(owner)) return Driver.Username;
187 if (owner == "*") return null;
188 return owner;
191 public VersionControlServer VersionControlServer
193 get { return Driver.VersionControlServer; }
196 public List<string> UnVerifiedFullPaths(string[] args)
198 List<string> paths = new List<string>();
199 for (int i = 0; i < args.Length; i++)
201 string fullPath = Path.GetFullPath(args[i]);
202 paths.Add(fullPath);
205 return paths;
208 public List<string> VerifiedFullPaths(string[] args)
210 List<string> paths = UnVerifiedFullPaths(args);
211 char[] wildcards = { '*', '?' };
213 foreach (string path in paths)
215 // skip wildcarded paths
216 if (-1 != path.IndexOfAny(wildcards)) continue;
218 if (!File.Exists(path) && !Directory.Exists(path))
220 Console.WriteLine("{0}: No such file or directory.", path);
221 Environment.Exit((int)ExitCode.Failure);
225 return paths;
228 public void DeleteReadOnlyFile(string fullName)
230 File.SetAttributes(fullName, FileAttributes.Normal);
231 File.Delete(fullName);
234 static public void ReadFileExcludes()
236 string exclusionList = Settings.Current.Get("File.Excludes");
237 if (String.IsNullOrEmpty(exclusionList)) return;
239 string separatorChar = Path.DirectorySeparatorChar.ToString();
240 string[] wildcards = exclusionList.Split(',');
242 StringBuilder dirRegexs = new StringBuilder();
243 StringBuilder fileRegexs = new StringBuilder();
245 foreach (string wildcard in wildcards)
247 if (-1 == wildcard.IndexOf(separatorChar))
249 if (0 != fileRegexs.Length) fileRegexs.Append("|");
251 fileRegexs.Append("^");
252 fileRegexs.Append(Regex.Escape(wildcard).Replace("\\*", ".*").Replace("\\?", "."));
253 fileRegexs.Append("$");
255 else
257 if (0 != dirRegexs.Length) dirRegexs.Append("|");
259 dirRegexs.Append("^.*");
260 dirRegexs.Append(Regex.Escape(wildcard));
261 dirRegexs.Append(".*$");
265 if (0 != fileRegexs.Length)
266 fileExcludes = new Regex(fileRegexs.ToString());
268 if (0 != dirRegexs.Length)
269 dirExcludes = new Regex(dirRegexs.ToString());
272 public bool IsExcludedFile(string path)
274 if ((fileExcludes != null) &&
275 (fileExcludes.IsMatch(Path.GetFileName(path))))
276 return true;
278 if ((dirExcludes != null) && (dirExcludes.IsMatch(path)))
279 return true;
281 return false;
284 public void ConfirmFilesSpecified()
286 if (Arguments.Length < 1)
288 Console.WriteLine("No files specified.");
289 Environment.Exit((int)ExitCode.Failure);
293 public string CanonicalPath(string p)
295 return p;
296 // maybe this feature is only interesting to me?
297 //if (runningOnUnix) return p;
298 //return p.Replace('\\', '/');
301 public abstract void Run ();