Example #1
0
        /// <summary>
        /// This is the main procedure
        /// </summary>
        /// <param name="args">Command line parameters</param>
        /// <returns>Error codes (0 for success, non-zero on Error)</returns>
        private int main(IEnumerable<string> args)
        {
            var options = args.Where(each => each.StartsWith("--")).Switches();
            var parameters = args.Parameters().ToArray();

            var buildinfo = string.Empty;

            Console.CancelKeyPress += (x, y) => {
                Console.WriteLine("Stopping ptk.");
                if (_cmdexe != null)
                    _cmdexe.Kill();
                if (_gitexe != null)
                    _gitexe.Kill();
                if (_hgexe != null)
                    _hgexe.Kill();
                if (_ptk != null)
                    _ptk.Kill();
            //                if (_traceexe != null) {
              //                  _traceexe.Kill();
            //            }
            };

            #region Parse Options

            // set up options which were defined by the user
            foreach (string arg in options.Keys) {
                IEnumerable<string> argumentParameters = options[arg];

                switch (arg) {
                    case "nologo":
                        // disable logo (will print "\n" anyway)
                        this.Assembly().SetLogo("");
                        break;

                    case "verbose":
                        _verbose = true;
                        break;

                    case "skip-built":
                        _skipBuilt = true;
                        _originalEnvironment.AddOrSet("skip-built", "true");
                        break;

                    case "load":
                        // user specified a custom PropertySheet
                        buildinfo = argumentParameters.LastOrDefault().GetFullPath();
                        if (!File.Exists(buildinfo)) {
                            return Fail("Unable to find buildinfo file [{0}]. \r\n\r\n    Use --help for command line help.", buildinfo);
                        }

                        break;

                    case "mingw-install":
                    case "msys-install":
                        _searchPaths += argumentParameters.LastOrDefault().GetFullPath() + ";";
                        break;

                    case "rescan-tools":
                        ProgramFinder.IgnoreCache = true;
                        break;

                    case "show-tools":
                        _showTools = true;
                        break;

                    case "help":
                        return Help();

                    default:
                        var p = argumentParameters.LastOrDefault();
                        if (string.IsNullOrEmpty(p)) {
                            if( _originalEnvironment.ContainsKey(arg) ) {
                                _originalEnvironment.Remove(arg);
                            }
                        } else{
                            _originalEnvironment.AddOrSet(arg, p);
                        }
                        break;
                }
            }

            // _originalEnvironment.Add("COAPP", CoApp.Toolkit.Engine.PackageManagerSettings.CoAppRootDirectory);
            _originalEnvironment.AddOrSet("COAPP", "C:/programdata/");

            while (string.IsNullOrEmpty(buildinfo) || !File.Exists(buildinfo)) {
                // if the user didn't pass in the file, walk up the tree to find the first directory that has a COPKG\.buildinfo file
                buildinfo = (from a in @".\COPKG\".DirectoryEnumerateFilesSmarter("*.buildinfo", SearchOption.TopDirectoryOnly)
                                     orderby a.Length ascending
                                     select a.GetFullPath()).FirstOrDefault() ?? @".\COPKG\.buildinfo".GetFullPath();

                // try the parent directory.
                var p = Path.GetDirectoryName(Environment.CurrentDirectory);
                if (string.IsNullOrEmpty(p)) {
                    return Fail("Unable to find buildinfo file [COPKG\\.buildinfo]--Even walking up the current tree.\r\n\r\n    Use --help for command line help.");
                }
                Environment.CurrentDirectory = p;
            }

            // make sure that we're in the parent directory of the .buildinfo file.
            Environment.CurrentDirectory = Path.GetDirectoryName(Path.GetDirectoryName(buildinfo));

            sessionFeeds = new[] {Environment.CurrentDirectory, Path.GetDirectoryName(buildinfo)};

            // tell the user what we are
            Logo();

            #endregion

            // connect to coapp service

            // set up several tools we need
            _cmdexe = new ProcessUtility("cmd.exe");
            //var f = new ProgramFinder("").ScanForFile("trace.exe");

            //if(!string.IsNullOrEmpty(f)) {
                //_traceexe = new ProcessUtility(new ProgramFinder("").ScanForFile("trace.exe"));
            //}

            _ptk = new ProcessUtility(Assembly.GetEntryAssembly().Location);
            // if this package is tracked by git, we can use git
            _useGit = Directory.Exists(".git".GetFullPath());            // if this package is tracked by mercurial, we can use mercurial
            _useHg = _useGit ? false : Directory.Exists(".hg".GetFullPath());

            // source control is mandatory! create a repository for this package
            if (!(_useGit || _useHg) && _verbose) {
                Console.WriteLine("WARNING: Source should be checked out using git or hg-git.");
            }

            // find git in the file system
            // - we prefer the CMD script over git.exe
            // git.exe may be located at "C:\Program Files\Git\bin"
            // git.cmd may be located at "C:\Program Files\Git\cmd"
            if (_useGit) {
                if (_verbose) {
                    Console.WriteLine("Using git for verification");
                }
                // attemt to find git.cmd
                _gitcmd = ProgramFinder.ProgramFilesAndDotNet.ScanForFile("git.cmd");
                _gitexe = null;
                if (string.IsNullOrEmpty(_gitcmd)) {
                    var f = ProgramFinder.ProgramFilesAndDotNet.ScanForFile("git.exe");
                    if (string.IsNullOrEmpty(f)) {
                        return Fail("Can not find git.cmd or git.exe (required to perform verification.)");
                    }
                    _gitexe = new ProcessUtility(ProgramFinder.ProgramFilesAndDotNet.ScanForFile("git.exe"));
                }
            }

            if (_useHg) {
                var f = ProgramFinder.ProgramFilesAndDotNet.ScanForFile("hg.exe");
                if (string.IsNullOrEmpty(f)) {
                    return Fail("Can not find hg.exe (required to perform verification.)");
                }
                _hgexe = new ProcessUtility(f);
            }

            // find sdk batch files.

            /* FIXME: URGENT.
             * C:\Program Files (x86)\Microsoft Visual Studio 8\VC\vcvarsall.bat
                C:\Program Files (x86)\Microsoft Visual Studio 8\VC\bin\vcvars32.bat
                C:\Program Files (x86)\Microsoft Visual Studio 8\VC\bin\amd64\vcvarsamd64.bat
                C:\Program Files (x86)\Microsoft Visual Studio 8\VC\bin\x86_amd64\vcvarsx86_amd64.bat
             * VC7.0: C:\Program Files\Microsoft Visual Studio .NET\Vc7\bin\vcvars32.bat

             * */

            _setenvcmd71 = ProgramFinder.ProgramFilesAndDotNetAndSdk.ScanForFile("setenv.cmd", excludeFilters: new[] { @"\Windows Azure SDK\**" , "winddk**" }, includeFilters: new [] {"sdk**", "v7.1**"}, rememberMissingFile:true, tagWithCosmeticVersion:"7.1");
            _setenvcmd7 = ProgramFinder.ProgramFilesAndDotNetAndSdk.ScanForFile("setenv.cmd", excludeFilters: new[] { @"\Windows Azure SDK\**", "7.1**", "winddk**" }, includeFilters: new[] { "sdk**", "v7**" }, rememberMissingFile: true, tagWithCosmeticVersion: "7.0");
            _setenvcmd6 = ProgramFinder.ProgramFilesAndDotNetAndSdk.ScanForFile("setenv.cmd", excludeFilters: new[] { @"\Windows Azure SDK\**", "winddk**" }, includeFilters: new[] { "sdk**", "6**" }, rememberMissingFile: true, tagWithCosmeticVersion: "6");

            _wdksetenvcmd7600 = ProgramFinder.ProgramFilesAndDotNetAndSdk.ScanForFile("setenv.bat", excludeFilters: new[] { @"\Windows Azure SDK\**"}, includeFilters: new[] { "winddk**"  }, rememberMissingFile: true, tagWithCosmeticVersion: "7600.16385.1");

            /// SDK Setenv (sdk2003): c:\program files (x86)\Microsoft SDK\SetEnv.bat

            _vcvarsallbat10 = ProgramFinder.ProgramFilesAndDotNetAndSdk.ScanForFile("vcvarsall.bat", includeFilters: new[] { "vc**", "10.0**" }, rememberMissingFile: true, tagWithCosmeticVersion: "10.0");
            _vcvarsallbat9 = ProgramFinder.ProgramFilesAndDotNetAndSdk.ScanForFile("vcvarsall.bat", includeFilters: new[] { "vc**", "9.0**" }, rememberMissingFile: true, tagWithCosmeticVersion: "9.0");
            _vcvarsallbat8 = ProgramFinder.ProgramFilesAndDotNetAndSdk.ScanForFile("vcvarsall.bat", includeFilters: new[] { "vc**", "8**" }, rememberMissingFile: true, tagWithCosmeticVersion: "8");
            _vcvarsallbat7 = ProgramFinder.ProgramFilesAndDotNetAndSdk.ScanForFile("vcvarsall.bat", includeFilters: new[] { "vc**", "7.0**" }, rememberMissingFile: true, tagWithCosmeticVersion: "7.0");
            _vcvarsallbat71 = ProgramFinder.ProgramFilesAndDotNetAndSdk.ScanForFile("vcvarsall.bat", includeFilters: new[] { "vc**", "7.1**" }, rememberMissingFile: true, tagWithCosmeticVersion: "7.1");
            _vcvars32bat = ProgramFinder.ProgramFilesAndDotNetAndSdk.ScanForFile("vcvars32.bat", includeFilters: new[] { "vc98**" }, rememberMissingFile: true, tagWithCosmeticVersion: "6");

            // _originalEnvironment.AddOrSet("COAPP", "C:/programdata/");
            var sdks = new List<string>();
            if (_setenvcmd71 != null) {
                sdks.Add("sdk7.1");
            }
            if (_setenvcmd7 != null) {
                sdks.Add("sdk7");
            }
            if (_setenvcmd6 != null) {
                sdks.Add("sdk6");
            }

            _originalEnvironment.AddOrSet("installed_sdks", sdks.Aggregate((s, s1) => s + ", " + s1));

            var compilers = new List<string>();

            if( _vcvarsallbat10 != null ) {
                compilers.Add("vc10");
            }
            if( _vcvarsallbat9 != null ) {
                compilers.Add("vc9");
            }
            if( _vcvarsallbat8 != null ) {
                compilers.Add("vc8");
            }
            if( _vcvarsallbat71 != null ) {
                compilers.Add("vc7.1");
            }
            if( _vcvarsallbat7 != null ) {
                compilers.Add("vc7");
            }
            if( _vcvars32bat != null ) {
                compilers.Add("vc6");
            }

            _originalEnvironment.AddOrSet("installed_compilers", sdks.Aggregate((s, s1) => s + ", " + s1));

            if (_showTools) {
                if (_useGit) {
                    Console.WriteLine("Git: {0}", _gitcmd ??  (_gitexe != null ? _gitexe.Executable : "Not-Found"));
                }
                if (_useHg) {
                    Console.WriteLine("hg: {0}", _hgexe.Executable);
                }
                Console.WriteLine("SDK Setenv (7.1): {0}", _setenvcmd71 ?? "Not-Found");
                Console.WriteLine("SDK Setenv (7.0): {0}", _setenvcmd7 ?? "Not-Found");
                Console.WriteLine("SDK Setenv (6): {0}", _setenvcmd6 ?? "Not-Found");

                Console.WriteLine("VC vcvarsall (10.0): {0}", _vcvarsallbat10 ?? "Not-Found");
                Console.WriteLine("VC vcvarsall (9.0): {0}", _vcvarsallbat9 ?? "Not-Found");
                Console.WriteLine("VC vcvarsall (8.0): {0}", _vcvarsallbat8 ?? "Not-Found");
                Console.WriteLine("VC vcvarsall (7.0): {0}", _vcvarsallbat7 ?? "Not-Found");
                Console.WriteLine("VC vcvarsall (7.1): {0}", _vcvarsallbat71 ?? "Not-Found");
                Console.WriteLine("VC vcvars32 (6): {0}", _vcvars32bat ?? "Not-Found");

                Console.WriteLine("ptk: {0}", _ptk.Executable);
                //Console.WriteLine("trace: {0}", _traceexe.Executable);
            }

            // tell the user we can't work without instructions
            if (!parameters.Any()) {
                return Fail("Missing action . \r\n\r\n    Use --help for command line help.");
            }

            // load property sheet (that is the .buildinfo file by default)
            _propertySheet = null;
            try {
                // load and parse. propertySheet will contain everything else we need for later
                _propertySheet = PropertySheet.Load(buildinfo);

                DefineRules = _propertySheet.Rules.Where(each => each.Id == "define" && each.Name == "*").ToArray();

                _propertySheet.GetMacroValue += (valueName) => {
                    if (valueName == "DEFAULTLAMBDAVALUE") {
                        return ".";
                    }

                    string defaultValue = null;
                    if( valueName.Contains("??")) {
                        var parts = valueName.Split(new[] {'?'}, StringSplitOptions.RemoveEmptyEntries);
                        defaultValue = parts.Length > 1 ? parts[1].Trim() : string.Empty;
                        valueName = parts[0];
                    }

                     var property = (from rule in DefineRules where rule.HasProperty(valueName) select rule[valueName]).FirstOrDefault();

                     if (property != null && property.HasValues && property.Values.Count() > 1) {
                         // it's a collection of values.
                         // let's take the collection and return it as a comma seperated string.
                         return property.Values.Aggregate((s, s1) => s + ", " + s1);
                     }

                    return (from rule in DefineRules where rule.HasProperty(valueName) select rule[valueName].Value).FirstOrDefault() ?? Environment.GetEnvironmentVariable(valueName) ?? defaultValue;
                };

                _propertySheet.GetCollection += (collectionName) => {
                    var property = (from rule in DefineRules where rule.HasProperty(collectionName) select rule[collectionName]).FirstOrDefault();
                    if( property != null && property.HasValues && property.Values.Count() > 1 ) {
                        return property.Values;
                    }
                    var collection = _propertySheet.GetMacroValue(collectionName);
                    return collection != null ? collection.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(each => each.Trim()) : Enumerable.Empty<object>();
                };
            }
            catch (EndUserParseException pspe) {
                using (new ConsoleColors(ConsoleColor.Yellow, ConsoleColor.Black)) {
                    Console.Write(pspe.Message);
                    Console.WriteLine("--found '{0}'", pspe.Token.Data);
                }

                return Fail("Error parsing .buildinfo file");
            }

            var builds = from rule in _propertySheet.Rules where rule.Name != "*" && (rule.HasProperty("default") && rule["default"].Value.IsTrue()) select rule;
            var command = string.Empty;

            switch(parameters.FirstOrDefault().ToLower()) {
                case "build ":
                case "clean":
                case "verify":
                case "status":
                case "trace":
                case "list":
                    command = parameters.FirstOrDefault().ToLower();
                    parameters = parameters.Skip(1).ToArray();
                    break;

                default:
                    command = "build";
                    break;
            }
            if (parameters.Any()) {
                var allbuilds = from rule in _propertySheet.Rules where rule.Name != "*" select rule;
                builds = parameters.Aggregate(Enumerable.Empty<Rule>(), (current, p) => current.Union(from build in allbuilds where build.Name.NewIsWildcardMatch(p) select build));
            }

            // are there even builds present?
            if(!builds.Any() ) {
                return Fail("No valid build configurations selected.");
            }

            // do the user's bidding
            try {
                switch (command) {
                    case "build":
                        ResetEnvironment();
                        Build(builds);

                        break;
                    case "clean":
                        ResetEnvironment();
                        Clean(builds);
                        using (new ConsoleColors(ConsoleColor.White, ConsoleColor.Black)) {
                            Console.WriteLine("Project Cleaned.");
                        }
                        break;
                    case "verify":
                        ResetEnvironment();
                        // Clean(builds); // clean up other builds in the list first.
                        Verify(builds);
                        using (new ConsoleColors(ConsoleColor.White, ConsoleColor.Black)) {
                            Console.WriteLine("Project Verified.");
                        }
                        break;
                    case "status":
                        ResetEnvironment();
                        Status(builds);
                        using (new ConsoleColors(ConsoleColor.White, ConsoleColor.Black)) {
                            Console.WriteLine("Project is in clean state.");
                        }
                        break;
                    //case "trace":
                      //  Trace(builds);
                        //break;
                    case "list":
                        Console.WriteLine("Buildinfo from [{0}]\r\n", buildinfo);
                        (from build in builds
                            let compiler = build["compiler"]
                            let sdk = build["sdk"]
                            let platform = build["platform"]
                            let targets = build["targets"]
                            select new {
                                Configuration = build.Name,
                                Compiler = compiler != null ? compiler.Value : "sdk7.1",
                                Sdk = sdk != null ? sdk.Value : "sdk7.1",
                                Platform = platform != null ? platform.Value.NormalizePlatform() : "x86",
                                Number_of_Outputs = targets != null ? targets.Values.Count() : 0
                            }).ToTable().ConsoleOut();
                        break;
                    default:
                        return Fail("'{0}' is not a valid command. \r\n\r\n    Use --help for assistance.", command);
                }
            }
            catch (ConsoleException e) {
                // these exceptions are expected
                return Fail("   {0}", e.Message);
            }
            catch (Exception e) {
                // it's probably okay to crash within proper commands (because something else crashed)
                Console.WriteLine(e.StackTrace);
                return Fail("   {0}", e.Message);
            }

            return 0;
        }