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
.Reflection
;
31 using System
.Collections
.Generic
;
32 using System
.Collections
.Specialized
;
36 using System
.Security
.Cryptography
.X509Certificates
;
37 using Mono
.GetOptions
;
38 using Microsoft
.TeamFoundation
;
39 using Microsoft
.TeamFoundation
.Client
;
40 using Microsoft
.TeamFoundation
.VersionControl
.Client
;
41 using Microsoft
.TeamFoundation
.Server
;
43 [assembly
: AssemblyTitle ("tf.exe")]
44 [assembly
: AssemblyVersion ("0.5.3")]
45 [assembly
: AssemblyDescription ("Team Foundation Source Control Tool")]
46 [assembly
: AssemblyCopyright ("(c) Joel W. Reed")]
48 [assembly
: Mono
.UsageComplement ("")]
50 [assembly
: Mono
.About("Team Foundation Source Control Tool")]
51 [assembly
: Mono
.Author ("Joel W. Reed")]
53 public partial class Driver
: ICertificatePolicy
, ICredentialsProvider
55 private CredentialCache credentialCache
= new CredentialCache();
56 private TeamFoundationServer _tfs
;
57 private VersionControlServer _versionControl
;
58 private DriverOptions Options
= new DriverOptions();
59 private string[] Arguments
;
61 private string domain
;
62 private string username
;
63 private string password
;
64 private string serverUrl
;
65 private List
<string> outputBuffer
= null;
67 public void WriteLine(string x
)
69 if (outputBuffer
!= null) outputBuffer
.Add(x
);
70 else Console
.WriteLine(x
);
73 public void WriteLine()
86 public string Username
94 private string ServerNameToUrl(string server
)
96 if (server
.StartsWith("http://") || server
.StartsWith("https://"))
99 return String
.Format("http://{0}:8080/", server
);
102 public string ServerUrl
105 if (!String
.IsNullOrEmpty(serverUrl
)) return serverUrl
;
107 if (!String
.IsNullOrEmpty(Options
.Server
))
108 return ServerNameToUrl(Options
.Server
);
110 WorkspaceInfo info
= Workstation
.Current
.GetLocalWorkspaceInfo(Environment
.CurrentDirectory
);
113 string server
= Settings
.Current
.Get("Server.Default");
114 if (!String
.IsNullOrEmpty(server
))
115 return ServerNameToUrl(server
);
117 Console
.WriteLine("Unable to determine the team foundation server");
118 Console
.WriteLine(" hint: try adding /server:<ip|name>");
119 Environment
.Exit((int)ExitCode
.Failure
);
122 serverUrl
= info
.ServerUri
.ToString();
127 private string GetLogin()
129 if (!String
.IsNullOrEmpty(Options
.Login
))
130 return Options
.Login
;
133 string login
= TfsKeyring
.GetCredentials(ServerUrl
);
134 if (!String
.IsNullOrEmpty(login
)) return login
;
136 // finally prompt if permitted
137 if (Options
.NoPrompt
) return String
.Empty
;
138 return PromptForLogin(ServerUrl
);
141 private void GetUserCredentials()
143 if (! String
.IsNullOrEmpty(username
)) return;
145 string login
= GetLogin();
146 string userinfo
= "";
148 int comma
= login
.IndexOf(",");
151 userinfo
= login
.Substring(0, comma
);
152 password
= login
.Substring(comma
+1);
154 else userinfo
= login
;
156 // try to find domain portion if given
157 int slash
= userinfo
.IndexOf('\\');
160 domain
= userinfo
.Substring(0, slash
);
161 username
= userinfo
.Substring(slash
+1);
165 int atsign
= userinfo
.IndexOf('@');
168 username
= userinfo
.Substring(0, atsign
);
169 domain
= userinfo
.Substring(atsign
+1);
177 public TeamFoundationServer TeamFoundationServer
181 if (null != _tfs
) return _tfs
;
183 ICredentials credentials
= GetCredentials(new Uri(ServerUrl
), null);
184 _tfs
= new TeamFoundationServer(ServerUrl
, credentials
);
190 // ICredentialsProvider method
191 public ICredentials
GetCredentials(Uri uri
, ICredentials failedCredentials
)
193 NetworkCredential creds
= credentialCache
.GetCredential(uri
, "NTLM");
194 if (creds
!= null) return creds
;
196 GetUserCredentials();
198 if (!(String
.IsNullOrEmpty(username
)) && String
.IsNullOrEmpty(password
)
199 && !Options
.NoPrompt
)
201 Console
.Write("Password: ");
202 password
= Console
.ReadLine();
205 creds
= new NetworkCredential(username
, password
, domain
);
206 credentialCache
.Add(uri
, "NTLM", creds
);
210 // ICredentialsProvider method
211 public void NotifyCredentialsAuthenticated (Uri uri
)
215 public VersionControlServer VersionControlServer
219 if (null != _versionControl
) return _versionControl
;
220 _versionControl
= (VersionControlServer
) TeamFoundationServer
.GetService(typeof(VersionControlServer
));
222 _versionControl
.Conflict
+= ConflictEventHandler
;
223 _versionControl
.NonFatalError
+= ExceptionEventHandler
;
225 // save credentials if passed
226 bool saveSetting
= Settings
.Current
.GetAsBool("Credentials.Save");
227 if (saveSetting
&& !String
.IsNullOrEmpty(Options
.Login
))
228 TfsKeyring
.SetCredentials(ServerUrl
, domain
, username
, password
);
230 return _versionControl
;
234 public Driver(string[] args
)
237 Options
.ProcessArgs(args
);
240 static void ConflictEventHandler(Object sender
, ConflictEventArgs e
)
242 Console
.Error
.WriteLine(e
.Message
);
245 static void ExceptionEventHandler(Object sender
, ExceptionEventArgs e
)
247 // sometimes e.Failure is null, not sure why yet
248 if (e
.Failure
!= null)
249 Console
.Error
.WriteLine(e
.Failure
.Message
);
252 private bool IsOption(string arg
)
254 if (String
.IsNullOrEmpty(arg
)) return false;
255 return (arg
[0] == '-' || arg
[0] == '/');
258 public void ProcessAllCommands()
260 List
<string> cmdArgs
= new List
<string>();
262 for (int i
=0; i
< Arguments
.Length
; i
++)
264 // a little padding between chained command output
265 if (i
> 0) Console
.WriteLine();
267 // unknown options are not sub commands
268 string scmd
= Arguments
[i
].ToLower();
275 if (outputBuffer
!= null)
277 foreach (string line
in outputBuffer
)
282 // pull in the rest of the args for this subcommand
284 for (j
=i
+1; j
< Arguments
.Length
; j
++)
286 string arg
= Arguments
[j
];
288 // command chaining options
289 if (arg
== "%") break;
292 // buffered output across command chain
293 outputBuffer
= new List
<string>();
297 // read more args from stdin
301 if (Console
.In
.Peek() != -1)
303 while ( (line
= Console
.ReadLine()) != null )
313 ProcessCommand(scmd
, cmdArgs
.ToArray());
319 public void ProcessCommand(string cmd
, string[] cmdArgs
)
321 Type commandType
= CommandRegistry
.GetCommandType(cmd
);
322 if (commandType
== null)
324 Console
.WriteLine("Unknown command: " + cmd
);
325 Environment
.Exit((int)ExitCode
.UnrecognizedCommand
);
328 Command command
= (Command
) Activator
.CreateInstance(commandType
, new object[]{ this, cmdArgs }
);
332 // ignoring certificate errors
333 public bool CheckValidationResult (ServicePoint sp
,
334 X509Certificate certificate
, WebRequest request
, int error
)
339 public static void Main(string[] args
)
341 Driver driver
= new Driver(args
);
342 ServicePointManager
.CertificatePolicy
= driver
;
344 if (args
.Length
== 0) {
345 HelpCommand cmd
= new HelpCommand(driver
, args
);
350 // basic auth doesn't seem to work well on mono when POSTing
351 // large data sets via a webservice.
352 AuthenticationManager
.Unregister("Basic");
356 driver
.ProcessAllCommands();
357 Environment
.Exit((int)ExitCode
.Success
);
359 catch (TeamFoundationServerException e
)
361 Console
.Error
.WriteLine(e
.Message
);
362 //Console.WriteLine(driver.Domain + "\\" + driver.Username);