using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Diagnostics;
using System.Threading;
using Perforce.P4;
namespace sln.bld.cmd
{
class Program
{
static String ServerSpec;
static String User;
static String Password;
static String Workspace;
static String Target;
static String MsBuildPathTxt = "C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\msbuild.exe";
private static void Usage()
{
Console.WriteLine(@"sln-bld-cmd -s host:port -u user [-p password] [-c workspace] <depot path of solution file to build>");
}
private static void ParseArgs(string[] args)
{
for (int idx = 0; idx < args.Length; idx++)
{
switch (args[idx].ToLower())
{
default:
Target = args[idx];
break;
case "-h":
Usage();
Environment.Exit(0);
break;
case "/?":
Usage();
Environment.Exit(0);
break;
case "-s":
ServerSpec = args[++idx];
break;
case "-u":
User = args[++idx];
break;
case "-p":
Password = args[++idx];
break;
case "-c":
Workspace = args[++idx];
break;
}
}
}
private static void ReadSettings()
{
if (!System.IO.File.Exists("config.txt"))
return;
using (StreamReader sr = new StreamReader("config.txt"))
{
ServerSpec = sr.ReadLine();
User = sr.ReadLine();
Password = sr.ReadLine();
Workspace = sr.ReadLine();
}
}
static void Main(string[] args)
{
ReadSettings();
ParseArgs(args);
if (String.IsNullOrWhiteSpace(ServerSpec))
{
Console.WriteLine("Must specify a server connection (host:port)!");
Environment.Exit(1);
}
if (String.IsNullOrWhiteSpace(User))
{
Console.WriteLine("Must specify a user!");
Environment.Exit(1);
}
DateTime buildTime = DateTime.Now;
String buildId = buildTime.ToString("MMddyyHHmmss");
String buildFolder = buildTime.ToString("MM-dd-yy_HHmmss");
String buildPath = Path.Combine(Environment.CurrentDirectory, buildFolder);
int idx = 0;
while ((Directory.Exists(buildPath)) && (idx < 26))
{
buildPath = Path.Combine(Environment.CurrentDirectory, buildTime.ToString("MM-dd-yy HHmmss") + ((char)((int)'a' + idx)));
}
if (idx >= 26)
Environment.Exit(1);
Directory.CreateDirectory(buildPath);
Server pServer = new Server(new ServerAddress(ServerSpec));
Repository rep = new Repository(pServer);
using (Connection con = rep.Connection)
{
con.UserName = User;
con.Client = new Client();
con.Client.Name = Workspace;
Options options = new Options();
options["Password"] = Password;
con.Connect(options);
Client buildClient = new Client();
buildClient.Name = "p4apinet_solution_builder_sample_application_client";
buildClient.OwnerName = User;
buildClient.ViewMap = new ViewMap();
buildClient.Root = buildPath;
buildClient.Options = ClientOption.AllWrite;
buildClient.LineEnd = LineEnd.Local;
buildClient.SubmitOptions = new ClientSubmitOptions(false, SubmitType.SubmitUnchanged);
string depotPath = Target;
if (Target.EndsWith(".sln"))
{
depotPath = Target.Substring(0, Target.LastIndexOf('/'));
}
string depotFolder = depotPath.Substring(depotPath.LastIndexOf('/') + 1);
depotPath += "/...";
String clientPath = String.Format("//{0}/{1}/...", buildClient.Name, depotFolder);
MapEntry entry = new MapEntry(MapType.Include, new DepotPath(depotPath), new ClientPath(clientPath));
buildClient.ViewMap.Add(entry);
Console.Write("Creating "+buildClient.Name+"...\r\n");
rep.CreateClient(buildClient);
con.Disconnect(null);
con.Client = new Client();
con.Client.Name = buildClient.Name;
con.Connect(options);
Console.Write("Running command 'p4 sync -p...\r\n");
Options sFlags = new Options(SyncFilesCmdFlags.PopulateClient, -1);
IList<FileSpec> rFiles = con.Client.SyncFiles(sFlags, null);
Console.Write("Deleting " + buildClient.Name + "...\r\n");
rep.DeleteClient(buildClient, null);
string localPath = clientPath;
localPath = localPath.TrimStart('/');
localPath = localPath.TrimEnd('.');
localPath = localPath.Substring(localPath.IndexOf('/') + 1);
localPath = localPath.Replace('/', '\\');
string solutionName = Target.Substring(depotPath.LastIndexOf('/'));
solutionName = solutionName.TrimStart('/');
localPath = Path.Combine(buildPath, localPath, solutionName);
RunBuidProc(localPath);
}
}
static Process buildProc;
private static void RunBuidProc(String SolutionFilePath)
{
buildProc = new Process();
string quotedPath = string.Format("\"{0}\"", SolutionFilePath);
ProcessStartInfo si = new ProcessStartInfo(MsBuildPathTxt, quotedPath);
si.UseShellExecute = false;
si.RedirectStandardOutput = true;
si.RedirectStandardError = true;
si.WorkingDirectory = Path.GetDirectoryName(SolutionFilePath);
si.CreateNoWindow = false;
buildProc.StartInfo = si;
Thread stdoutThread = new Thread(new ThreadStart(ReadStandardOutThreadProc));
stdoutThread.IsBackground = true;
Thread stderrThread = new Thread(new ThreadStart(ReadStandardErrorThreadProc));
stderrThread.IsBackground = true;
buildProc.Start();
stdoutThread.Start();
stderrThread.Start();
buildProc.WaitForExit();
if (stdoutThread.IsAlive)
stdoutThread.Abort();
if (stderrThread.IsAlive)
stderrThread.Abort();
buildProc = null;
return;
}
private static void ReadStandardOutThreadProc() //Process p, TextBox t)
{
try
{
String line;
while ((line = buildProc.StandardOutput.ReadLine()) != null)
{
Console.WriteLine(line);
}
return;
}
catch (ThreadAbortException) { return; }
}
private static void ReadStandardErrorThreadProc() //Process p, TextBox t)
{
try
{
String line;
while ((line = buildProc.StandardError.ReadLine()) != null)
{
Console.WriteLine(line);
}
return;
}
catch (ThreadAbortException) { return; }
}
}
}