public TeamCityProject(XElement e)
        {
            Id   = e.Attribute("id").Value;
            Name = e.Attribute("name").Value;
            Href = e.Attribute("href").Value;
            var p = e.Element("parentProject");

            if (p != null)
            {
                Parent = new TeamCityProject(p);
            }
            var c = e.Element("projects");

            if (c != null && c.HasElements)
            {
                Children = new List <TeamCityProject>(c.Elements("project").Select(x => new TeamCityProject(x)));
            }
            var b = e.Element("buildTypes");

            if (b != null && b.HasElements)
            {
                BuildConfigurations = new List <TeamCityBuildConfiguration>(b.Elements("buildType").Select(x => new TeamCityBuildConfiguration(x, this)));
            }
        }
        public static void Run(string discoveryFolder, string templateFolder, string teamCityUrl, string teamCityUsername, string teamCityPassword, bool overwrite, IMessageObserver observer)
        {
            var buildProjects = Directory.GetFiles(discoveryFolder, "*.sln", SearchOption.AllDirectories)
                                .Select(x => new BuildProject(x));

            foreach (var buildProject in buildProjects)
            {
                TeamCityProject tcp         = null;
                var             projectTree = buildProject.Name.Split('.').ToList();
                projectTree.Add(buildProject.Branch.Replace(".", string.Empty));
                for (var i = 0; i < projectTree.Count; i++)
                {
                    var projectId = string.Join("_", projectTree.GetRange(0, i + 1));
                    tcp = GetProject(projectId, teamCityUrl, teamCityUsername, teamCityPassword);
                    if ((i == (projectTree.Count - 1)) && overwrite && tcp != null && tcp.BuildConfigurations != null && tcp.BuildConfigurations.Any())
                    {
                        DeleteProject(tcp.Id, teamCityUrl, teamCityUsername, teamCityPassword);
                        tcp = null;
                    }
                    if (tcp == null)
                    {
                        observer.Notify("CreateProject: {0}", projectId);
                        tcp = CreateProject(projectTree[i], projectId, string.Join("_", projectTree.GetRange(0, i)),
                                            teamCityUrl, teamCityUsername, teamCityPassword);
                    }
                    else
                    {
                        observer.Notify("{0} exists", projectId);
                    }
                }
                if (tcp != null)
                {
                    foreach (var buildConfig in new[] { "Build", "Drop", "Release" })
                    {
                        var buildId = string.Concat(tcp.Id, "_", buildConfig);
                        if (overwrite || tcp.BuildConfigurations == null || !tcp.BuildConfigurations.Any(x => x.Id.Equals(buildId)))
                        {
                            observer.Notify("/{0}", buildId.Replace('_', '/'));
                            var bc  = CreateBuildConfiguration(buildConfig, buildId, tcp.Id, teamCityUrl, teamCityUsername, teamCityPassword);
                            var xml = XDocument.Load(Path.Combine(templateFolder, string.Concat(buildConfig, ".xml"))).Root;
                            observer.Notify(" - Settings");
                            foreach (var setting in xml.Descendants("option").Select(x => new { Name = x.Attribute("name").Value, x.Attribute("value").Value }))
                            {
                                var url     = string.Concat(teamCityUrl, "/httpAuth/app/rest/buildTypes/", bc.Id, "/settings/", setting.Name);
                                var payload = (setting.Name == "buildNumberPattern" && buildConfig != "Build")
                                    ? string.Format(setting.Value, buildConfig == "Drop" ? buildId.Replace("_Drop", "_Build") : buildId.Replace("_Release", "_Drop"))
                                    : setting.Value;
                                observer.Notify("  - Setting: {0}, value: {1}", setting.Name, payload);
                                Put(url, payload, teamCityUsername, teamCityPassword);
                            }
                            observer.Notify(" - Parameters");
                            foreach (var param in xml.Descendants("param").Select(x => new { Name = x.Attribute("name").Value, x.Attribute("value").Value }))
                            {
                                var url     = string.Concat(teamCityUrl, "/httpAuth/app/rest/buildTypes/", bc.Id, "/parameters/", param.Name);
                                var payload = param.Value;
                                observer.Notify("  - Parameter: {0}, value: {1}", param.Name, payload);
                                Put(url, payload, teamCityUsername, teamCityPassword);
                            }
                            observer.Notify(" - Steps");
                            foreach (var stepXml in xml.Descendants("step"))
                            {
                                //build step special case: package web application for web deploy. repeat step for each web project in solution.
                                switch (stepXml.Attribute("id").Value)
                                {
                                case "RUNNER_128":
                                    foreach (var sp in buildProject.Solution.Projects.Where(x => x.OutputClass == OutputClass.WebDeploy))
                                    {
                                        observer.Notify("  - Step: {0}", stepXml.Attribute("name").Value.Replace("{0}", sp.ProjectName));
                                        Post(
                                            string.Concat(teamCityUrl, "/httpAuth/app/rest/buildTypes/", bc.Id, "/steps"),
                                            stepXml.ToString()
                                            .Replace("{0}", sp.ProjectName)
                                            .Replace("{1}", Path.Combine("Source", sp.RelativePath)),
                                            teamCityUsername, teamCityPassword);
                                    }
                                    break;

                                default:
                                    observer.Notify("  - Step: {0}", stepXml.Attribute("name").Value);
                                    Post(
                                        string.Concat(teamCityUrl, "/httpAuth/app/rest/buildTypes/", bc.Id, "/steps"),
                                        stepXml.ToString().Replace("{0}", string.Concat(@"Source\", buildProject.Name, ".sln")),
                                        teamCityUsername, teamCityPassword);
                                    break;
                                }
                            }
                            observer.Notify(" - Features");
                            foreach (var featureXml in xml.Descendants("feature").Select(x => x.ToString()))
                            {
                                Post(
                                    string.Concat(teamCityUrl, "/httpAuth/app/rest/buildTypes/", bc.Id, "/features"),
                                    featureXml,
                                    teamCityUsername, teamCityPassword);
                            }
                            observer.Notify(" - Triggers");
                            foreach (var triggerXml in xml.Descendants("trigger").Select(x => x.ToString()))
                            {
                                Post(
                                    string.Concat(teamCityUrl, "/httpAuth/app/rest/buildTypes/", bc.Id, "/triggers"),
                                    triggerXml,
                                    teamCityUsername, teamCityPassword);
                            }
                            switch (buildConfig)
                            {
                            case "Build":
                                if (/*buildProject.Artifacts.Any()*/ true)
                                {
                                    observer.Notify(" - Artifacts");
                                    Put(
                                        string.Concat(teamCityUrl, "/httpAuth/app/rest/buildTypes/", bc.Id, "/settings/artifactRules"),
                                        string.Join("\n", buildProject.Solution.Projects.Where(x => x.Artifact != null).Select(x => string.Format("{0} => {1}.zip", x.Artifact.RelativePath, x.Artifact.Name))),
                                        teamCityUsername, teamCityPassword);
                                }
                                if (!string.IsNullOrWhiteSpace(buildProject.VcsRoot) && buildProject.VcsRoot.StartsWith("//depot/", StringComparison.InvariantCultureIgnoreCase))
                                {
                                    observer.Notify(" - VcsRoots");
                                    Post(
                                        string.Concat(teamCityUrl, "/httpAuth/app/rest/vcs-roots"),
                                        string.Format(File.ReadAllText(Path.Combine(templateFolder, "vcs-p4.xml")),
                                                      string.Concat(tcp.Id, "_Source"),
                                                      "Source",
                                                      tcp.Id,
                                                      tcp.Name,
                                                      buildProject.VcsRoot,
                                                      "svc_tcbuild_dev",
                                                      "Gti%xEkf&amp;8yj"),
                                        teamCityUsername, teamCityPassword);
                                    foreach (var vcsRootXml in xml.Descendants("vcs-root-entry").Select(x => x.ToString()))
                                    {
                                        observer.Notify("  - VcsRoot: {0}", string.Concat(tcp.Id, "_Source"));
                                        Post(
                                            string.Concat(teamCityUrl, "/httpAuth/app/rest/buildTypes/", bc.Id, "/vcs-root-entries"),
                                            string.Format(vcsRootXml,
                                                          string.Concat(tcp.Id, "_Source"),
                                                          "Source"),
                                            teamCityUsername, teamCityPassword);
                                    }
                                }
                                break;

                            case "Drop":
                                observer.Notify(" - ArtifactDependencies");
                                foreach (var dependencyXml in xml.Descendants("artifact-dependency").Select(x => x.ToString()))
                                {
                                    observer.Notify("  - ArtifactDependency: {0}", buildId.Replace("_Drop", "_Build"));
                                    Post(
                                        string.Concat(teamCityUrl, "/httpAuth/app/rest/buildTypes/", bc.Id, "/artifact-dependencies"),
                                        string.Format(dependencyXml,
                                                      buildId.Replace("_Drop", "_Build"),
                                                      "Build",
                                                      tcp.Id,
                                                      tcp.Name,
                                                      //test this dependency artifact rule when you get back from the pub!
                                                      string.Join("&#xD;&#xA;", buildProject.Solution.Projects.Where(x => x.Artifact != null).Select(x => string.Format("+:{0}.zip!** =&gt; {0}", x.Artifact.Name)))),
                                        teamCityUsername, teamCityPassword);
                                }
                                observer.Notify(" - SnapshotDependencies");
                                foreach (var dependencyXml in xml.Descendants("snapshot-dependency").Select(x => x.ToString()))
                                {
                                    observer.Notify("  - SnapshotDependency: {0}", buildId.Replace("_Drop", "_Build"));
                                    Post(
                                        string.Concat(teamCityUrl, "/httpAuth/app/rest/buildTypes/", bc.Id, "/snapshot-dependencies"),
                                        string.Format(dependencyXml,
                                                      buildId.Replace("_Drop", "_Build"),
                                                      "Build",
                                                      tcp.Id,
                                                      tcp.Name),
                                        teamCityUsername, teamCityPassword);
                                }
                                observer.Notify(" - VcsRoots");
                                Post(
                                    string.Concat(teamCityUrl, "/httpAuth/app/rest/vcs-roots"),
                                    string.Format(File.ReadAllText(Path.Combine(templateFolder, "vcs-robocopy.xml")),
                                                  string.Concat(tcp.Id, "_RoboCopy"),
                                                  "RoboCopy",
                                                  tcp.Id,
                                                  tcp.Name),
                                    teamCityUsername, teamCityPassword);
                                foreach (var vcsRootXml in xml.Descendants("vcs-root-entry").Select(x => x.ToString()))
                                {
                                    observer.Notify("  - VcsRoot: {0}", string.Concat(tcp.Id, "_RoboCopy"));
                                    Post(
                                        string.Concat(teamCityUrl, "/httpAuth/app/rest/buildTypes/", bc.Id, "/vcs-root-entries"),
                                        string.Format(vcsRootXml,
                                                      string.Concat(tcp.Id, "_RoboCopy"),
                                                      "RoboCopy"),
                                        teamCityUsername, teamCityPassword);
                                }
                                observer.Notify(" - Artifacts");
                                Put(
                                    string.Concat(teamCityUrl, "/httpAuth/app/rest/buildTypes/", bc.Id, "/settings/artifactRules"),
                                    @"%drop_folder%\%build.number% => artifacts.zip",
                                    teamCityUsername, teamCityPassword);
                                break;

                            case "Release":
                                observer.Notify(" - ArtifactDependencies");
                                foreach (var dependencyXml in xml.Descendants("artifact-dependency").Select(x => x.ToString()))
                                {
                                    observer.Notify("  -ArtifactDependency: {0}", buildId.Replace("_Release", "_Drop"));
                                    Post(
                                        string.Concat(teamCityUrl, "/httpAuth/app/rest/buildTypes/", bc.Id, "/artifact-dependencies"),
                                        string.Format(dependencyXml,
                                                      buildId.Replace("_Release", "_Drop"),
                                                      "Drop",
                                                      tcp.Id,
                                                      tcp.Name),
                                        teamCityUsername, teamCityPassword);
                                }
                                observer.Notify(" - SnapshotDependencies");
                                foreach (var dependencyXml in xml.Descendants("snapshot-dependency").Select(x => x.ToString()))
                                {
                                    observer.Notify("  - SnapshotDependency: {0}", buildId.Replace("_Release", "_Drop"));
                                    Post(
                                        string.Concat(teamCityUrl, "/httpAuth/app/rest/buildTypes/", bc.Id, "/snapshot-dependencies"),
                                        string.Format(dependencyXml,
                                                      buildId.Replace("_Release", "_Drop"),
                                                      "Drop",
                                                      tcp.Id,
                                                      tcp.Name),
                                        teamCityUsername, teamCityPassword);
                                }
                                break;
                            }
                        }
                    }
                }
            }
        }
 public TeamCityBuildConfiguration(XElement e, TeamCityProject project)
 {
     Id      = e.Attribute("id").Value;
     Name    = e.Attribute("name").Value;
     Project = project;
 }