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 WriteLine(string x
)
67 if (outputBuffer
!= null) outputBuffer
.Add(x
);
68 else Console
.WriteLine(x
);
71 public void WriteLine()
76 public string Username
79 string serverUrl
= GetServerUrl();
80 NetworkCredential creds
= credentialCache
.GetCredential(new Uri(serverUrl
), "NTLM");
81 if (creds
== null) return String
.Empty
;
82 return creds
.UserName
;
89 string serverUrl
= GetServerUrl();
90 NetworkCredential creds
= credentialCache
.GetCredential(new Uri(serverUrl
), "NTLM");
91 if (creds
== null) return String
.Empty
;
96 private string ServerNameToUrl(string server
)
98 if (server
.StartsWith("http://") || server
.StartsWith("https://"))
101 return String
.Format("http://{0}:8080/", server
);
104 public string GetServerUrl()
106 if (!String
.IsNullOrEmpty(Options
.Server
))
107 return ServerNameToUrl(Options
.Server
);
109 WorkspaceInfo info
= Workstation
.Current
.GetLocalWorkspaceInfo(Environment
.CurrentDirectory
);
112 string server
= Settings
.Current
.Get("Server.Default");
113 if (!String
.IsNullOrEmpty(server
))
114 return ServerNameToUrl(server
);
116 Console
.WriteLine("Unable to determine the team foundation server");
117 Console
.WriteLine(" hint: try adding /server:<ip|name>");
118 Environment
.Exit((int)ExitCode
.Failure
);
121 return info
.ServerUri
.ToString();
124 private string GetLogin(string url
)
126 if (!String
.IsNullOrEmpty(Options
.Login
))
127 return Options
.Login
;
130 string login
= Keyring
.GetCredentials(url
);
131 if (!String
.IsNullOrEmpty(login
)) return login
;
133 // finally prompt if permitted
134 if (Options
.NoPrompt
) return String
.Empty
;
135 return PromptForLogin(url
);
138 public TeamFoundationServer TeamFoundationServer
142 if (null != _tfs
) return _tfs
;
144 string url
= GetServerUrl();
145 ICredentials credentials
= GetCredentials(new Uri(url
), null);
146 _tfs
= new TeamFoundationServer(url
, credentials
);
152 // ICredentialsProvider method
153 public ICredentials
GetCredentials(Uri uri
, ICredentials failedCredentials
)
155 NetworkCredential creds
= credentialCache
.GetCredential(uri
, "NTLM");
156 if (creds
!= null) return creds
;
158 string url
= uri
.ToString();
159 creds
= new TFCredential(GetLogin(url
));
161 if (!(String
.IsNullOrEmpty(creds
.UserName
)) &&
162 String
.IsNullOrEmpty(creds
.Password
) && !Options
.NoPrompt
)
164 Console
.Write("Password: ");
165 creds
.Password
= Console
.ReadLine();
168 // save credentials if passed
169 bool saveSetting
= Settings
.Current
.GetAsBool("Credentials.Save");
170 if (saveSetting
&& !String
.IsNullOrEmpty(Options
.Login
))
171 Keyring
.SetCredentials(url
, creds
.Domain
, creds
.UserName
, creds
.Password
);
173 credentialCache
.Add(uri
, "NTLM", creds
);
177 // ICredentialsProvider method
178 public void NotifyCredentialsAuthenticated (Uri uri
)
182 public VersionControlServer VersionControlServer
186 if (null != _versionControl
) return _versionControl
;
187 _versionControl
= (VersionControlServer
) TeamFoundationServer
.GetService(typeof(VersionControlServer
));
189 _versionControl
.Conflict
+= ConflictEventHandler
;
190 _versionControl
.NonFatalError
+= ExceptionEventHandler
;
192 return _versionControl
;
196 public Driver(string[] args
)
199 Options
.ProcessArgs(args
);
202 static void ConflictEventHandler(Object sender
, ConflictEventArgs e
)
204 Console
.Error
.WriteLine(e
.Message
);
207 static void ExceptionEventHandler(Object sender
, ExceptionEventArgs e
)
209 // sometimes e.Failure is null, not sure why yet
210 if (e
.Failure
!= null)
211 Console
.Error
.WriteLine(e
.Failure
.Message
);
214 private bool IsOption(string arg
)
216 if (String
.IsNullOrEmpty(arg
)) return false;
217 return (arg
[0] == '-' || arg
[0] == '/');
220 public void ProcessAllCommands()
222 List
<string> cmdArgs
= new List
<string>();
224 for (int i
=0; i
< Arguments
.Length
; i
++)
226 // a little padding between chained command output
227 if (i
> 0) Console
.WriteLine();
229 // unknown options are not sub commands
230 string scmd
= Arguments
[i
].ToLower();
237 if (outputBuffer
!= null)
239 foreach (string line
in outputBuffer
)
244 // pull in the rest of the args for this subcommand
246 for (j
=i
+1; j
< Arguments
.Length
; j
++)
248 string arg
= Arguments
[j
];
250 // command chaining options
251 if (arg
== "%") break;
254 // buffered output across command chain
255 outputBuffer
= new List
<string>();
259 // read more args from stdin
263 if (Console
.In
.Peek() != -1)
265 while ( (line
= Console
.ReadLine()) != null )
275 ProcessCommand(scmd
, cmdArgs
.ToArray());
281 public void ProcessCommand(string cmd
, string[] cmdArgs
)
283 Type commandType
= CommandRegistry
.GetCommandType(cmd
);
284 if (commandType
== null)
286 Console
.WriteLine("Unknown command: " + cmd
);
287 Environment
.Exit((int)ExitCode
.UnrecognizedCommand
);
290 Command command
= (Command
) Activator
.CreateInstance(commandType
, new object[]{ this, cmdArgs }
);
294 // ignoring certificate errors
295 public bool CheckValidationResult (ServicePoint sp
,
296 X509Certificate certificate
, WebRequest request
,
302 public static void Main(string[] args
)
304 Driver driver
= new Driver(args
);
305 ServicePointManager
.CertificatePolicy
= driver
;
307 if (args
.Length
== 0) {
308 HelpCommand cmd
= new HelpCommand(driver
, args
);
313 // basic auth doesn't seem to work well on mono when POSTing
314 // large data sets via a webservice.
315 AuthenticationManager
.Unregister("Basic");
319 driver
.ProcessAllCommands();
320 Environment
.Exit((int)ExitCode
.Success
);
322 catch (TeamFoundationServerException e
)
324 Console
.Error
.WriteLine(e
.Message
);