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
.Net
.Security
;
37 using System
.Security
.Cryptography
.X509Certificates
;
38 using Mono
.GetOptions
;
39 using Microsoft
.TeamFoundation
;
40 using Microsoft
.TeamFoundation
.Client
;
41 using Microsoft
.TeamFoundation
.VersionControl
.Client
;
42 using Microsoft
.TeamFoundation
.Server
;
45 [assembly
: AssemblyTitle ("tf.exe")]
46 [assembly
: AssemblyVersion ("0.6.0")]
47 [assembly
: AssemblyDescription ("Team Foundation Source Control Tool")]
48 [assembly
: AssemblyCopyright ("(c) Joel W. Reed")]
50 [assembly
: Mono
.UsageComplement ("")]
52 [assembly
: Mono
.About("Team Foundation Source Control Tool")]
53 [assembly
: Mono
.Author ("Joel W. Reed")]
55 public partial class Driver
: ICertificatePolicy
, ICredentialsProvider
57 private TeamFoundationServer _tfs
;
58 private VersionControlServer _versionControl
;
59 private DriverOptions Options
= new DriverOptions();
60 private string[] Arguments
;
62 private CredentialCache credentialCache
= new CredentialCache();
63 private List
<string> outputBuffer
= null;
65 public void Write(string x
)
67 if (outputBuffer
!= null) outputBuffer
.Add(x
);
68 else Console
.Write(x
);
71 public void WriteLine(string x
)
73 if (outputBuffer
!= null) outputBuffer
.Add(x
);
74 else Console
.WriteLine(x
);
77 public void WriteLine()
82 public string Username
85 string serverUrl
= GetServerUrl();
86 NetworkCredential creds
= credentialCache
.GetCredential(new Uri(serverUrl
), "NTLM");
87 if (creds
== null) return String
.Empty
;
88 return creds
.UserName
;
95 string serverUrl
= GetServerUrl();
96 NetworkCredential creds
= credentialCache
.GetCredential(new Uri(serverUrl
), "NTLM");
97 if (creds
== null) return String
.Empty
;
102 private string ServerNameToUrl(string server
)
104 if (server
.StartsWith("http://") || server
.StartsWith("https://"))
107 return String
.Format("http://{0}:8080/", server
);
110 public string GetServerUrl()
112 if (!String
.IsNullOrEmpty(Options
.Server
))
113 return ServerNameToUrl(Options
.Server
);
115 WorkspaceInfo info
= Workstation
.Current
.GetLocalWorkspaceInfo(Environment
.CurrentDirectory
);
118 string server
= Settings
.Current
.Get("Server.Default");
119 if (!String
.IsNullOrEmpty(server
))
120 return ServerNameToUrl(server
);
122 Console
.WriteLine("Unable to determine the team foundation server");
123 Console
.WriteLine(" hint: try adding /server:<ip|name>");
124 Environment
.Exit((int)ExitCode
.Failure
);
127 return info
.ServerUri
.ToString();
130 private string GetLogin(string url
)
132 if (!String
.IsNullOrEmpty(Options
.Login
))
133 return Options
.Login
;
136 string login
= Keyring
.GetCredentials(url
);
137 if (!String
.IsNullOrEmpty(login
)) return login
;
139 // finally prompt if permitted
140 if (Options
.NoPrompt
) return String
.Empty
;
141 return PromptForLogin(url
);
144 public TeamFoundationServer TeamFoundationServer
148 if (null != _tfs
) return _tfs
;
150 string url
= GetServerUrl();
151 ICredentials credentials
= GetCredentials(new Uri(url
), null);
152 _tfs
= new TeamFoundationServer(url
, credentials
);
158 // ICredentialsProvider method
159 public ICredentials
GetCredentials(Uri uri
, ICredentials failedCredentials
)
161 NetworkCredential creds
= credentialCache
.GetCredential(uri
, "NTLM");
162 if (creds
!= null) return creds
;
164 string url
= uri
.ToString();
165 string login
= GetLogin(url
);
167 if (String
.IsNullOrEmpty(login
)) return null;
168 creds
= new TFCredential(login
);
170 if (!(String
.IsNullOrEmpty(creds
.UserName
)) &&
171 String
.IsNullOrEmpty(creds
.Password
) && !Options
.NoPrompt
)
173 Console
.Write("Password: ");
174 creds
.Password
= Console
.ReadLine();
177 // save credentials if passed
178 bool saveSetting
= Settings
.Current
.GetAsBool("Credentials.Save");
179 if (saveSetting
&& !String
.IsNullOrEmpty(Options
.Login
))
180 Keyring
.SetCredentials(url
, creds
.Domain
, creds
.UserName
, creds
.Password
);
182 credentialCache
.Add(uri
, "NTLM", creds
);
186 // ICredentialsProvider method
187 public void NotifyCredentialsAuthenticated (Uri uri
)
191 public VersionControlServer VersionControlServer
195 if (null != _versionControl
) return _versionControl
;
196 _versionControl
= (VersionControlServer
) TeamFoundationServer
.GetService(typeof(VersionControlServer
));
198 _versionControl
.Conflict
+= ConflictEventHandler
;
199 _versionControl
.NonFatalError
+= ExceptionEventHandler
;
201 return _versionControl
;
205 public Driver(string[] args
)
208 Options
.ProcessArgs(args
);
211 static void ConflictEventHandler(Object sender
, ConflictEventArgs e
)
213 Console
.Error
.WriteLine(e
.Message
);
216 static void ExceptionEventHandler(Object sender
, ExceptionEventArgs e
)
218 // sometimes e.Failure is null, not sure why yet
219 if (e
.Failure
!= null)
220 Console
.Error
.WriteLine(e
.Failure
.Message
);
223 private bool IsOption(string arg
)
225 if (String
.IsNullOrEmpty(arg
)) return false;
226 return (arg
[0] == '-' || arg
[0] == '/');
229 public void ProcessAllCommands()
231 List
<string> cmdArgs
= new List
<string>();
233 for (int i
=0; i
< Arguments
.Length
; i
++)
235 // a little padding between chained command output
236 if (i
> 0) Console
.WriteLine();
238 // unknown options are not sub commands
239 string scmd
= Arguments
[i
].ToLower();
246 if (outputBuffer
!= null)
248 foreach (string line
in outputBuffer
)
253 // pull in the rest of the args for this subcommand
255 for (j
=i
+1; j
< Arguments
.Length
; j
++)
257 string arg
= Arguments
[j
];
259 // command chaining options
260 if (arg
== "%") break;
263 // buffered output across command chain
264 outputBuffer
= new List
<string>();
268 // read more args from stdin
272 if (Console
.In
.Peek() != -1)
274 while ( (line
= Console
.ReadLine()) != null )
284 ProcessCommand(scmd
, cmdArgs
.ToArray());
290 public void ProcessCommand(string cmd
, string[] cmdArgs
)
292 Type commandType
= CommandRegistry
.GetCommandType(cmd
);
293 if (commandType
== null)
295 Console
.WriteLine("Unknown command: " + cmd
);
296 Environment
.Exit((int)ExitCode
.UnrecognizedCommand
);
299 Command command
= (Command
) Activator
.CreateInstance(commandType
, new object[]{ this, cmdArgs }
);
303 // ignoring certificate errors
304 public bool CheckValidationResult (ServicePoint sp
,
305 X509Certificate certificate
, WebRequest request
,
311 public static void Main(string[] args
)
313 Driver driver
= new Driver(args
);
314 ServicePointManager
.CertificatePolicy
= driver
;
316 if (args
.Length
== 0) {
317 HelpCommand cmd
= new HelpCommand(driver
, args
);
322 // basic auth doesn't seem to work well on mono when POSTing
323 // large data sets via a webservice.
324 AuthenticationManager
.Unregister("Basic");
328 driver
.ProcessAllCommands();
329 Environment
.Exit((int)ExitCode
.Success
);
331 catch (TeamFoundationServerException e
)
333 Console
.Error
.WriteLine(e
.Message
);