diff --git a/.gitignore b/.gitignore index e83ec6cd..79c619d0 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,5 @@ output *.TeamCitySharp.sln.metaproj* *.DotSettings.* nuget -Package \ No newline at end of file +Package +/TeamCitySharp.sln.ide diff --git a/TeamCitySharp.sln b/TeamCitySharp.sln index f368ed68..17b28371 100644 --- a/TeamCitySharp.sln +++ b/TeamCitySharp.sln @@ -1,6 +1,8 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2012 +# Visual Studio 2013 +VisualStudioVersion = 12.0.30723.0 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{263F35DD-20C1-4209-B121-E962C9328C70}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TeamCitySharp.IntegrationTests", "src\Tests\IntegrationTests\TeamCitySharp.IntegrationTests.csproj", "{BA409A09-CC7B-4A71-A3D4-FE27234A721B}" diff --git a/packages/EasyHttp.1.6.1.0/EasyHttp.1.6.1.0.nupkg b/packages/EasyHttp.1.6.1.0/EasyHttp.1.6.1.0.nupkg deleted file mode 100644 index 947bc18f..00000000 Binary files a/packages/EasyHttp.1.6.1.0/EasyHttp.1.6.1.0.nupkg and /dev/null differ diff --git a/packages/EasyHttp.1.6.1.0/lib/net40/EasyHttp.dll b/packages/EasyHttp.1.6.1.0/lib/net40/EasyHttp.dll deleted file mode 100644 index 109d6c89..00000000 Binary files a/packages/EasyHttp.1.6.1.0/lib/net40/EasyHttp.dll and /dev/null differ diff --git a/packages/EasyHttp.1.6.1.0/lib/sl40-wp/EasyHttp.dll b/packages/EasyHttp.1.6.1.0/lib/sl40-wp/EasyHttp.dll deleted file mode 100644 index 109d6c89..00000000 Binary files a/packages/EasyHttp.1.6.1.0/lib/sl40-wp/EasyHttp.dll and /dev/null differ diff --git a/packages/EasyHttp.1.6.1.0/lib/sl40/EasyHttp.dll b/packages/EasyHttp.1.6.1.0/lib/sl40/EasyHttp.dll deleted file mode 100644 index 109d6c89..00000000 Binary files a/packages/EasyHttp.1.6.1.0/lib/sl40/EasyHttp.dll and /dev/null differ diff --git a/packages/EasyHttp.1.6.67.0/EasyHttp.1.6.67.0.nupkg b/packages/EasyHttp.1.6.67.0/EasyHttp.1.6.67.0.nupkg new file mode 100644 index 00000000..768ca8f5 Binary files /dev/null and b/packages/EasyHttp.1.6.67.0/EasyHttp.1.6.67.0.nupkg differ diff --git a/packages/EasyHttp.1.6.67.0/lib/net40/EasyHttp.dll b/packages/EasyHttp.1.6.67.0/lib/net40/EasyHttp.dll new file mode 100644 index 00000000..df865744 Binary files /dev/null and b/packages/EasyHttp.1.6.67.0/lib/net40/EasyHttp.dll differ diff --git a/packages/EasyHttp.1.6.67.0/lib/net40/EasyHttp.pdb b/packages/EasyHttp.1.6.67.0/lib/net40/EasyHttp.pdb new file mode 100644 index 00000000..c8c35e2b Binary files /dev/null and b/packages/EasyHttp.1.6.67.0/lib/net40/EasyHttp.pdb differ diff --git a/packages/repositories.config b/packages/repositories.config index bcd17bb0..e2cb9c26 100644 --- a/packages/repositories.config +++ b/packages/repositories.config @@ -1,6 +1,6 @@  - + \ No newline at end of file diff --git a/src/TeamCitySharp/ActionTypes/Agents.cs b/src/TeamCitySharp/ActionTypes/Agents.cs index 56944acc..6b9837ee 100644 --- a/src/TeamCitySharp/ActionTypes/Agents.cs +++ b/src/TeamCitySharp/ActionTypes/Agents.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.IO; using TeamCitySharp.Connection; using TeamCitySharp.DomainEntities; @@ -13,11 +14,26 @@ internal Agents(TeamCityCaller caller) _caller = caller; } - public List All() + public List All(bool includeDisconnected = true, bool includeUnauthorized = true) { - var agentWrapper = _caller.Get("/app/rest/agents"); + var url = string.Format("/app/rest/agents?includeDisconnected={0}&includeUnauthorized={1}", + includeDisconnected.ToString().ToLower(), includeUnauthorized.ToString().ToLower()); + + var agentWrapper = _caller.Get(url); return agentWrapper.Agent; } + + private string AddqueryString(string url, string queryString) + { + if (url.Contains("?")) + url += "&"; + else + url += "?"; + + url += queryString; + + return url; + } } } \ No newline at end of file diff --git a/src/TeamCitySharp/ActionTypes/BuildConfigs.cs b/src/TeamCitySharp/ActionTypes/BuildConfigs.cs index cdcd4a0f..ac52cb19 100644 --- a/src/TeamCitySharp/ActionTypes/BuildConfigs.cs +++ b/src/TeamCitySharp/ActionTypes/BuildConfigs.cs @@ -114,6 +114,24 @@ public void PostRawBuildTrigger(BuildTypeLocator locator, string rawXml) _caller.PostFormat(rawXml, HttpContentTypes.ApplicationXml, "/app/rest/buildTypes/{0}/triggers", locator); } + public void SetArtifactDependency(BuildTypeLocator locator, ArtifactDependency dependency) + { + _caller.PostFormat(dependency, HttpContentTypes.ApplicationJson, + HttpContentTypes.ApplicationJson, "/app/rest/buildTypes/{0}/artifact-dependencies", locator); + } + + public void SetSnapshotDependency(BuildTypeLocator locator, SnapshotDependency dependency) + { + _caller.PostFormat(dependency, HttpContentTypes.ApplicationJson, + HttpContentTypes.ApplicationJson, "/app/rest/buildTypes/{0}/snapshot-dependencies", locator); + } + + public void SetTrigger(BuildTypeLocator locator, BuildTrigger trigger) + { + _caller.PostFormat(trigger, HttpContentTypes.ApplicationJson, HttpContentTypes.ApplicationJson, + "/app/rest/buildTypes/{0}/triggers", locator); + } + public void SetConfigurationParameter(BuildTypeLocator locator, string key, string value) { _caller.PutFormat(value, HttpContentTypes.TextPlain, "/app/rest/buildTypes/{0}/parameters/{1}", locator, key); @@ -209,5 +227,11 @@ public BuildConfig BuildType(BuildTypeLocator locator) return build; } + + public string CopyConfiguration(BuildTypeLocator projectLocator, BuildTypeLocator locatorToCopy, string newName) + { + _caller.PostFormat(string.Format("", newName, locatorToCopy), HttpContentTypes.ApplicationXml, "/app/rest/projects/{0}/buildTypes", projectLocator); + return ByConfigurationName(newName).Id; + } } } \ No newline at end of file diff --git a/src/TeamCitySharp/ActionTypes/Builds.cs b/src/TeamCitySharp/ActionTypes/Builds.cs index 4c52f340..5c1889ab 100644 --- a/src/TeamCitySharp/ActionTypes/Builds.cs +++ b/src/TeamCitySharp/ActionTypes/Builds.cs @@ -16,6 +16,13 @@ internal Builds(TeamCityCaller caller) _caller = caller; } + public Build ByBuildInternalId(string buildInternalId) + { + var build = _caller.GetFormat("/app/rest/builds/id:{0}", buildInternalId); + + return build; + } + public List ByBuildLocator(BuildLocator locator) { var buildWrapper = _caller.GetFormat("/app/rest/builds?locator={0}", locator); @@ -95,6 +102,13 @@ public Build LastErrorBuildByBuildConfigId(string buildConfigId) return builds != null ? builds.FirstOrDefault() : new Build(); } + public Build ById(string id) + { + var build = _caller.GetFormat("/app/rest/builds/id:{0}", id); + + return build ?? new Build(); + } + public List ByBuildConfigId(string buildConfigId) { return ByBuildLocator(BuildLocator.WithDimensions(BuildTypeLocator.WithId(buildConfigId) @@ -145,5 +159,11 @@ public List NonSuccessfulBuildsForUser(string userName) return builds.Where(b => b.Status != "SUCCESS").ToList(); } + + public void PinBuildByBuildNumber(string buildConfigId, string buildNumber, string message) + { + message = message == null ? string.Empty : message; + _caller.Put(message, "text/plain", string.Format("/app/rest/builds/buildType:{0},number:{1}/{2}/", buildConfigId, buildNumber, "pin"), null); + } } } \ No newline at end of file diff --git a/src/TeamCitySharp/ActionTypes/Changes.cs b/src/TeamCitySharp/ActionTypes/Changes.cs index 5218b4aa..dd0b6d78 100644 --- a/src/TeamCitySharp/ActionTypes/Changes.cs +++ b/src/TeamCitySharp/ActionTypes/Changes.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using TeamCitySharp.Connection; using TeamCitySharp.DomainEntities; @@ -30,17 +31,23 @@ public Change ByChangeId(string id) public List ByBuildConfigId(string buildConfigId) { - var changeWrapper = _caller.GetFormat("/app/rest/changes?buildType={0}", buildConfigId); + var changeWrapper = _caller.GetFormat("/app/rest/changes?buildType=id:{0}", buildConfigId); return changeWrapper.Change; } + public List ByBuildConfigIdSinceChangeId(string buildConfigId, string sinceChangeId) + { + var changeWrapper = _caller.GetFormat("/app/rest/changes?buildType=id:{0}&sinceChange=id:{1}", buildConfigId, sinceChangeId); + + return changeWrapper.Change; + } + public Change LastChangeDetailByBuildConfigId(string buildConfigId) { var changes = ByBuildConfigId(buildConfigId); return changes.FirstOrDefault(); } - } } \ No newline at end of file diff --git a/src/TeamCitySharp/ActionTypes/IAgents.cs b/src/TeamCitySharp/ActionTypes/IAgents.cs index 36b5ade5..1292b1a3 100644 --- a/src/TeamCitySharp/ActionTypes/IAgents.cs +++ b/src/TeamCitySharp/ActionTypes/IAgents.cs @@ -5,6 +5,6 @@ namespace TeamCitySharp.ActionTypes { public interface IAgents { - List All(); + List All(bool includeDisconnected = false, bool includeUnauthorized = false); } } \ No newline at end of file diff --git a/src/TeamCitySharp/ActionTypes/IBuildConfigs.cs b/src/TeamCitySharp/ActionTypes/IBuildConfigs.cs index 2829ec2d..0491f7b5 100644 --- a/src/TeamCitySharp/ActionTypes/IBuildConfigs.cs +++ b/src/TeamCitySharp/ActionTypes/IBuildConfigs.cs @@ -22,9 +22,15 @@ public interface IBuildConfigs void SetConfigurationSetting(BuildTypeLocator locator, string settingName, string settingValue); bool GetConfigurationPauseStatus(BuildTypeLocator locator); void SetConfigurationPauseStatus(BuildTypeLocator locator, bool isPaused); + void PostRawArtifactDependency(BuildTypeLocator locator, string rawXml); + void SetArtifactDependency(BuildTypeLocator locator, ArtifactDependency dependency); + void PostRawBuildStep(BuildTypeLocator locator, string rawXml); + void PostRawBuildTrigger(BuildTypeLocator locator, string rawXml); + void SetTrigger(BuildTypeLocator locator, BuildTrigger trigger); + void SetConfigurationParameter(BuildTypeLocator locator, string key, string value); void PostRawAgentRequirement(BuildTypeLocator locator, string rawXml); void DeleteBuildStep(BuildTypeLocator locator, string buildStepId); @@ -33,6 +39,8 @@ public interface IBuildConfigs void DeleteParameter(BuildTypeLocator locator, string parameterName); void DeleteBuildTrigger(BuildTypeLocator locator, string buildTriggerId); + string CopyConfiguration(BuildTypeLocator locatorToCopy, BuildTypeLocator locator, string newName); + /// /// Makes a build type inherit a template. /// @@ -62,6 +70,7 @@ public interface IBuildConfigs /// ]]> /// void PostRawSnapshotDependency(BuildTypeLocator locator, XmlElement rawXml); + void SetSnapshotDependency(BuildTypeLocator locator, SnapshotDependency dependency); /// /// Locates a build type by its locator. diff --git a/src/TeamCitySharp/ActionTypes/IBuilds.cs b/src/TeamCitySharp/ActionTypes/IBuilds.cs index 6afba988..dcf6d2cd 100644 --- a/src/TeamCitySharp/ActionTypes/IBuilds.cs +++ b/src/TeamCitySharp/ActionTypes/IBuilds.cs @@ -7,6 +7,7 @@ namespace TeamCitySharp.ActionTypes { public interface IBuilds { + Build ByBuildInternalId(string buildInternalId); List SuccessfulBuildsByBuildConfigId(string buildConfigId); Build LastSuccessfulBuildByBuildConfigId(string buildConfigId); List FailedBuildsByBuildConfigId(string buildConfigId); @@ -14,6 +15,7 @@ public interface IBuilds Build LastBuildByBuildConfigId(string buildConfigId); List ErrorBuildsByBuildConfigId(string buildConfigId); Build LastErrorBuildByBuildConfigId(string buildConfigId); + Build ById(string id); List ByBuildConfigId(string buildConfigId); List ByConfigIdAndTag(string buildConfigId, string tag); List ByUserName(string userName); @@ -24,5 +26,6 @@ public interface IBuilds List ByBranch(string branchName); Build LastBuildByAgent(string agentName); void Add2QueueBuildByBuildConfigId(string buildConfigId); + void PinBuildByBuildNumber(string buildConfigId, string buildNumber, string message); } } \ No newline at end of file diff --git a/src/TeamCitySharp/ActionTypes/IChanges.cs b/src/TeamCitySharp/ActionTypes/IChanges.cs index 1ae51cd5..54796afd 100644 --- a/src/TeamCitySharp/ActionTypes/IChanges.cs +++ b/src/TeamCitySharp/ActionTypes/IChanges.cs @@ -9,5 +9,6 @@ public interface IChanges Change ByChangeId(string id); Change LastChangeDetailByBuildConfigId(string buildConfigId); List ByBuildConfigId(string buildConfigId); + List ByBuildConfigIdSinceChangeId(string buildConfigId, string sinceChangeId); } } \ No newline at end of file diff --git a/src/TeamCitySharp/Connection/ITeamCityCaller.cs b/src/TeamCitySharp/Connection/ITeamCityCaller.cs index aee4df5c..ec6a95f8 100644 --- a/src/TeamCitySharp/Connection/ITeamCityCaller.cs +++ b/src/TeamCitySharp/Connection/ITeamCityCaller.cs @@ -27,7 +27,7 @@ internal interface ITeamCityCaller void Get(string urlPart); - T Post(string data, string contenttype, string urlPart, string accept); + T Post(object data, string contenttype, string urlPart, string accept); bool Authenticate(string urlPart); diff --git a/src/TeamCitySharp/Connection/TeamCityCaller.cs b/src/TeamCitySharp/Connection/TeamCityCaller.cs index 8f2cbadf..7a197a9f 100644 --- a/src/TeamCitySharp/Connection/TeamCityCaller.cs +++ b/src/TeamCitySharp/Connection/TeamCityCaller.cs @@ -42,17 +42,17 @@ public void GetFormat(string urlPart, params object[] parts) public T PostFormat(object data, string contenttype, string accept, string urlPart, params object[] parts) { - return Post(data.ToString(), contenttype, string.Format(urlPart, parts), accept); + return Post(data, contenttype, string.Format(urlPart, parts), accept); } public void PostFormat(object data, string contenttype, string urlPart, params object[] parts) { - Post(data.ToString(), contenttype, string.Format(urlPart, parts), string.Empty); + Post(data, contenttype, string.Format(urlPart, parts), string.Empty); } public void PutFormat(object data, string contenttype, string urlPart, params object[] parts) { - Put(data.ToString(), contenttype, string.Format(urlPart, parts), string.Empty); + Put(data, contenttype, string.Format(urlPart, parts), string.Empty); } public void DeleteFormat(string urlPart, params object[] parts) @@ -144,7 +144,7 @@ private HttpResponse GetResponse(string urlPart) return response; } - public T Post(string data, string contenttype, string urlPart, string accept) + public T Post(object data, string contenttype, string urlPart, string accept) { return Post(data, contenttype, urlPart, accept).StaticBody(); } diff --git a/src/TeamCitySharp/Connection/TeamcityJsonEncoderDecoderConfiguration.cs b/src/TeamCitySharp/Connection/TeamcityJsonEncoderDecoderConfiguration.cs index 4a40a74f..13fd9185 100644 --- a/src/TeamCitySharp/Connection/TeamcityJsonEncoderDecoderConfiguration.cs +++ b/src/TeamCitySharp/Connection/TeamcityJsonEncoderDecoderConfiguration.cs @@ -1,9 +1,13 @@ using System.Collections.Generic; +using System.IO; using EasyHttp.Codecs; using EasyHttp.Codecs.JsonFXExtensions; using EasyHttp.Configuration; +using JsonFx.IO; using JsonFx.Json; +using JsonFx.Model; using JsonFx.Serialization; +using JsonFx.Serialization.Filters; namespace TeamCitySharp.Connection { @@ -11,7 +15,7 @@ public class TeamcityJsonEncoderDecoderConfiguration : IEncoderDecoderConfigurat { public IEncoder GetEncoder() { - var jsonWriter = new JsonWriter(new DataWriterSettings(DefaultEncoderDecoderConfiguration.CombinedResolverStrategy() + var jsonWriter = new CamelCaseJsonWriter(new DataWriterSettings(DefaultEncoderDecoderConfiguration.CombinedResolverStrategy() , new TeamCityDateFilter()), new[] { "application/.*json", "text/.*json" }); var writers = new List { jsonWriter }; @@ -19,8 +23,8 @@ public IEncoder GetEncoder() return new DefaultEncoder(dataWriterProvider); } - public IDecoder GetDecoder() - { + public IDecoder GetDecoder(bool shouldRemoveAtSign = true) + { var jsonReader = new JsonReader(new DataReaderSettings(DefaultEncoderDecoderConfiguration.CombinedResolverStrategy() , new TeamCityDateFilter()), new[] { "application/.*json", "text/.*json" }); @@ -29,4 +33,39 @@ public IDecoder GetDecoder() return new DefaultDecoder(dataReaderProvider); } } + + public class CamelCaseJsonWriter : JsonWriter + { + public CamelCaseJsonWriter(DataWriterSettings settings, params string[] contentTypes) + : base(settings, contentTypes) + {} + + protected override ITextFormatter GetFormatter() + { + return new CamelCaseJsonFormatter(this.Settings); + } + } + + public class CamelCaseJsonFormatter : JsonWriter.JsonFormatter + { + public CamelCaseJsonFormatter(DataWriterSettings settings) + : base(settings) + {} + + protected override void WritePropertyName(TextWriter writer, string propertyName) + { + base.WritePropertyName(writer, CamelCase(propertyName)); + } + + private static string CamelCase(string input) + { + if (string.IsNullOrEmpty(input)) + return input; + + var chars = input.ToCharArray(); + chars[0] = chars[0].ToString().ToLower().ToCharArray()[0]; + + return new string(chars); + } + } } \ No newline at end of file diff --git a/src/TeamCitySharp/DomainEntities/AgentRequirements.cs b/src/TeamCitySharp/DomainEntities/AgentRequirements.cs index 6f9afdbe..fa58cf28 100644 --- a/src/TeamCitySharp/DomainEntities/AgentRequirements.cs +++ b/src/TeamCitySharp/DomainEntities/AgentRequirements.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Web; namespace TeamCitySharp.DomainEntities { @@ -9,6 +10,22 @@ public override string ToString() return "agent-requirements"; } - public List AgentRequirement { get; set; } + public List AgentRequirement { get; set; } + + public string GetAsXml() + { + if (AgentRequirement == null) + return ""; + string result = string.Empty; + result += ""; + foreach (var item in AgentRequirement) + { + result += ""; + result += item.Properties.GetAsXml(); + result += ""; + } + result += ""; + return result; + } } } \ No newline at end of file diff --git a/src/TeamCitySharp/DomainEntities/ArtifactDependencies.cs b/src/TeamCitySharp/DomainEntities/ArtifactDependencies.cs index 82286b91..0e6c5bad 100644 --- a/src/TeamCitySharp/DomainEntities/ArtifactDependencies.cs +++ b/src/TeamCitySharp/DomainEntities/ArtifactDependencies.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Web; namespace TeamCitySharp.DomainEntities { @@ -10,5 +11,21 @@ public override string ToString() } public List ArtifactDependency { get; set; } + + public string GetAsXml() + { + if (ArtifactDependency == null) + return ""; + string result = string.Empty; + result += ""; + foreach (var item in ArtifactDependency) + { + result += ""; + result += item.Properties.GetAsXml(); + result += ""; + } + result += ""; + return result; + } } } \ No newline at end of file diff --git a/src/TeamCitySharp/DomainEntities/ArtifactDependency.cs b/src/TeamCitySharp/DomainEntities/ArtifactDependency.cs index 487b9565..4278a7c8 100644 --- a/src/TeamCitySharp/DomainEntities/ArtifactDependency.cs +++ b/src/TeamCitySharp/DomainEntities/ArtifactDependency.cs @@ -1,14 +1,40 @@ +using JsonFx.Json; + namespace TeamCitySharp.DomainEntities { public class ArtifactDependency { + public ArtifactDependency() + { + Properties = new Properties(); + Type = "artifact_dependency"; + } public override string ToString() { - return "artifact_dependency"; + return Type; } public string Id { get; set; } - public string Type { get; set; } public Properties Properties { get; set; } + [JsonName("source-buildType")] + public SourceBuildType SourceBuildType { get; set; } + public string Type { get; set; } + + public static ArtifactDependency Default(string dependsOnbuildId) + { + var dependency = new ArtifactDependency(); + + dependency.Properties.Add("cleanDestinationDirectory", "true"); + dependency.Properties.Add("pathRules", "* => Temp"); + dependency.Properties.Add("revisionName", "sameChainOrLastFinished"); + dependency.Properties.Add("revisionValue", "latest.sameChainOrLastFinished"); + + dependency.SourceBuildType = new SourceBuildType + { + Id = dependsOnbuildId + }; + + return dependency; + } } } \ No newline at end of file diff --git a/src/TeamCitySharp/DomainEntities/Build.cs b/src/TeamCitySharp/DomainEntities/Build.cs index 7d16fc34..7f2ae0a1 100644 --- a/src/TeamCitySharp/DomainEntities/Build.cs +++ b/src/TeamCitySharp/DomainEntities/Build.cs @@ -1,5 +1,5 @@ -using System; - +using System; + namespace TeamCitySharp.DomainEntities { public class Build @@ -11,12 +11,18 @@ public class Build public string Href { get; set; } public string WebUrl { get; set; } public string StatusText { get; set; } - public DateTime StartDate { get; set; } - public DateTime FinishDate { get; set; } + public string BranchName { get; set; } + public DateTime StartDate { get; set; } + public DateTime FinishDate { get; set; } public BuildConfig BuildConfig { get; set; } public Agent Agent { get; set;} - public ChangeWrapper Changes { get; set; } + + public ChangeWrapper Changes { get; set; } + /// + /// TeamCity 8.* response to build queries fills changes in LastChanges. + /// + public ChangeWrapper LastChanges { get; set; } public override string ToString() { diff --git a/src/TeamCitySharp/DomainEntities/BuildConfig.cs b/src/TeamCitySharp/DomainEntities/BuildConfig.cs index 93034b20..8cbaa486 100644 --- a/src/TeamCitySharp/DomainEntities/BuildConfig.cs +++ b/src/TeamCitySharp/DomainEntities/BuildConfig.cs @@ -1,20 +1,20 @@ -namespace TeamCitySharp.DomainEntities -{ - public class BuildConfig - { - public override string ToString() - { - return Name; - } - - public string Id { get; set; } - public string Name { get; set; } - public string Href { get; set; } - public string ProjectId { get; set; } - public string ProjectName { get; set; } - public string Description { get; set; } - public string WebUrl { get; set; } - +namespace TeamCitySharp.DomainEntities +{ + public class BuildConfig + { + public override string ToString() + { + return Name; + } + + public string Id { get; set; } + public string Name { get; set; } + public string Href { get; set; } + public string ProjectId { get; set; } + public string ProjectName { get; set; } + public string Description { get; set; } + public string WebUrl { get; set; } + public Project Project { get; set; } public Parameters Parameters { get; set; } @@ -23,7 +23,7 @@ public override string ToString() public VcsRootEntries VcsRootEntries { get; set; } public BuildSteps Steps { get; set; } public AgentRequirements AgentRequirements { get; set; } - public BuildTriggers Triggers { get; set; } - public Properties Settings { get; set; } + public BuildTriggers Triggers { get; set; } + public Properties Settings { get; set; } } } \ No newline at end of file diff --git a/src/TeamCitySharp/DomainEntities/BuildSteps.cs b/src/TeamCitySharp/DomainEntities/BuildSteps.cs index c0c35be1..607c467c 100644 --- a/src/TeamCitySharp/DomainEntities/BuildSteps.cs +++ b/src/TeamCitySharp/DomainEntities/BuildSteps.cs @@ -10,5 +10,21 @@ public override string ToString() } public List Step { get; set; } + + public string GetAsXml() + { + if (Step == null) + return ""; + string result = string.Empty; + result += ""; + foreach (var item in Step) + { + result += ""; + result += item.Properties.GetAsXml(); + result += ""; + } + result += ""; + return result; + } } } \ No newline at end of file diff --git a/src/TeamCitySharp/DomainEntities/BuildTrigger.cs b/src/TeamCitySharp/DomainEntities/BuildTrigger.cs index f6f9ec78..96a954ac 100644 --- a/src/TeamCitySharp/DomainEntities/BuildTrigger.cs +++ b/src/TeamCitySharp/DomainEntities/BuildTrigger.cs @@ -2,6 +2,11 @@ namespace TeamCitySharp.DomainEntities { public class BuildTrigger { + public BuildTrigger() + { + Properties = new Properties(); + } + public override string ToString() { return "trigger"; @@ -10,5 +15,18 @@ public override string ToString() public string Id { get; set; } public string Type { get; set; } public Properties Properties { get; set; } + + public static BuildTrigger FinishBuildTrigger(string dependsOnbuildId) + { + var trigger = new BuildTrigger + { + Type = "buildDependencyTrigger" + }; + + trigger.Properties.Add("afterSuccessfulBuildOnly", "true"); + trigger.Properties.Add("dependsOn", dependsOnbuildId); + + return trigger; + } } } \ No newline at end of file diff --git a/src/TeamCitySharp/DomainEntities/BuildTriggers.cs b/src/TeamCitySharp/DomainEntities/BuildTriggers.cs index 0fbe5cc2..13bcbec0 100644 --- a/src/TeamCitySharp/DomainEntities/BuildTriggers.cs +++ b/src/TeamCitySharp/DomainEntities/BuildTriggers.cs @@ -10,5 +10,21 @@ public override string ToString() } public List Trigger { get; set; } + + public string GetAsXml() + { + if (Trigger == null) + return ""; + string result = string.Empty; + result += ""; + foreach (var item in Trigger) + { + result += ""; + result += item.Properties.GetAsXml(); + result += ""; + } + result += ""; + return result; + } } } \ No newline at end of file diff --git a/src/TeamCitySharp/DomainEntities/NewProjectDescription.cs b/src/TeamCitySharp/DomainEntities/NewProjectDescription.cs new file mode 100644 index 00000000..42ccf97d --- /dev/null +++ b/src/TeamCitySharp/DomainEntities/NewProjectDescription.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using JsonFx.Json; +using TeamCitySharp.Locators; + +namespace TeamCitySharp.DomainEntities +{ + public class NewProjectDescription + { + public string Name { get; set; } + public string Id { get; set; } + public ParentProjectWrapper ParentProject { get; set; } + } +} diff --git a/src/TeamCitySharp/DomainEntities/ParentProjectWrapper.cs b/src/TeamCitySharp/DomainEntities/ParentProjectWrapper.cs new file mode 100644 index 00000000..2bec04da --- /dev/null +++ b/src/TeamCitySharp/DomainEntities/ParentProjectWrapper.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using TeamCitySharp.Locators; + +namespace TeamCitySharp.DomainEntities +{ + public class ParentProjectWrapper + { + private readonly ProjectLocator _locator; + + public ParentProjectWrapper(ProjectLocator locator) + { + _locator = locator; + } + + public string Locator { get { return _locator.ToString(); } } + } +} diff --git a/src/TeamCitySharp/DomainEntities/Properties.cs b/src/TeamCitySharp/DomainEntities/Properties.cs index bb13d698..7457de88 100644 --- a/src/TeamCitySharp/DomainEntities/Properties.cs +++ b/src/TeamCitySharp/DomainEntities/Properties.cs @@ -1,13 +1,38 @@ using System.Collections.Generic; +using System.Web; namespace TeamCitySharp.DomainEntities { public class Properties { + public Properties() + { + Property = new List(); + } + + public void Add(string name, string value) + { + Property.Add(new Property(name, value)); + } + public override string ToString() { return "properties"; } public List Property { get; set; } + + public string GetAsXml() + { + if (Property == null) + return ""; + string result = string.Empty; + result += ""; + foreach (var property in Property) + { + result += ""; + } + result += ""; + return result; + } } } \ No newline at end of file diff --git a/src/TeamCitySharp/DomainEntities/Property.cs b/src/TeamCitySharp/DomainEntities/Property.cs index 70f3cb25..d2dadab0 100644 --- a/src/TeamCitySharp/DomainEntities/Property.cs +++ b/src/TeamCitySharp/DomainEntities/Property.cs @@ -2,6 +2,15 @@ namespace TeamCitySharp.DomainEntities { public class Property { + public Property() + {} + + public Property(string name, string value) + { + Name = name; + Value = value; + } + public override string ToString() { return Name; diff --git a/src/TeamCitySharp/DomainEntities/SnapshotDependencies.cs b/src/TeamCitySharp/DomainEntities/SnapshotDependencies.cs index cd44b4f0..7bd0bb28 100644 --- a/src/TeamCitySharp/DomainEntities/SnapshotDependencies.cs +++ b/src/TeamCitySharp/DomainEntities/SnapshotDependencies.cs @@ -10,5 +10,21 @@ public override string ToString() } public List SnapshotDependency { get; set; } - } + + public string GetAsXml() + { + if (SnapshotDependency == null) + return ""; + string result = string.Empty; + result += ""; + foreach (var item in SnapshotDependency) + { + result += ""; + result += item.Properties.GetAsXml(); + result += ""; + } + result += ""; + return result; + } + } } \ No newline at end of file diff --git a/src/TeamCitySharp/DomainEntities/SnapshotDependency.cs b/src/TeamCitySharp/DomainEntities/SnapshotDependency.cs index 6f0cfe50..2cfeb3df 100644 --- a/src/TeamCitySharp/DomainEntities/SnapshotDependency.cs +++ b/src/TeamCitySharp/DomainEntities/SnapshotDependency.cs @@ -1,13 +1,41 @@ +using JsonFx.Json; + namespace TeamCitySharp.DomainEntities { public class SnapshotDependency { + public SnapshotDependency() + { + Properties = new Properties(); + Type = "snapshot_dependency"; + } + public override string ToString() { - return "snapshot_dependency"; + return Type; } public string Id { get; set; } - public Properties Properties { get; set; } + public Properties Properties { get; set; } + [JsonName("source-buildType")] + public SourceBuildType SourceBuildType { get; set; } + public string Type { get; set; } + + public static SnapshotDependency Default(string dependsOnbuildId) + { + var dependency = new SnapshotDependency(); + + dependency.Properties.Add("run-build-if-dependency-failed", "false"); + dependency.Properties.Add("run-build-on-the-same-agent", "false"); + dependency.Properties.Add("take-started-build-with-same-revisions", "true"); + dependency.Properties.Add("take-successful-builds-only", "true"); + + dependency.SourceBuildType = new SourceBuildType + { + Id = dependsOnbuildId + }; + + return dependency; + } } } \ No newline at end of file diff --git a/src/TeamCitySharp/DomainEntities/SourceBuildType.cs b/src/TeamCitySharp/DomainEntities/SourceBuildType.cs new file mode 100644 index 00000000..e5c1f89f --- /dev/null +++ b/src/TeamCitySharp/DomainEntities/SourceBuildType.cs @@ -0,0 +1,7 @@ +namespace TeamCitySharp.DomainEntities +{ + public class SourceBuildType + { + public string Id { get; set; } + } +} diff --git a/src/TeamCitySharp/DomainEntities/VcsRootEntries.cs b/src/TeamCitySharp/DomainEntities/VcsRootEntries.cs index 6a18f42b..ecba7234 100644 --- a/src/TeamCitySharp/DomainEntities/VcsRootEntries.cs +++ b/src/TeamCitySharp/DomainEntities/VcsRootEntries.cs @@ -10,5 +10,22 @@ public override string ToString() } public List VcsRootEntry { get; set; } + + public string GetAsXml() + { + if (VcsRootEntry == null) + return ""; + string result = string.Empty; + result += ""; + foreach (var item in VcsRootEntry) + { + result += ""; + result += ""; + result += ""; + result += ""; + } + result += ""; + return result; + } } } \ No newline at end of file diff --git a/src/TeamCitySharp/ITeamCityClient.cs b/src/TeamCitySharp/ITeamCityClient.cs index f63f97d3..f8c6f3c8 100644 --- a/src/TeamCitySharp/ITeamCityClient.cs +++ b/src/TeamCitySharp/ITeamCityClient.cs @@ -1,4 +1,4 @@ -using TeamCitySharp.ActionTypes; +using TeamCitySharp.ActionTypes; namespace TeamCitySharp { @@ -7,7 +7,7 @@ public interface ITeamCityClient void Connect(string userName, string password); void ConnectAsGuest(); bool Authenticate(); - + IBuilds Builds { get; } IBuildConfigs BuildConfigs { get; } IProjects Projects { get; } @@ -16,6 +16,6 @@ public interface ITeamCityClient IAgents Agents { get; } IVcsRoots VcsRoots { get; } IChanges Changes { get; } - IBuildArtifacts Artifacts { get; } + IBuildArtifacts Artifacts { get; } } } \ No newline at end of file diff --git a/src/TeamCitySharp/Locators/ProjectLocator.cs b/src/TeamCitySharp/Locators/ProjectLocator.cs new file mode 100644 index 00000000..5291db9c --- /dev/null +++ b/src/TeamCitySharp/Locators/ProjectLocator.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; + +namespace TeamCitySharp.Locators +{ + public class ProjectLocator + { + public static ProjectLocator WithId(string id) + { + return new ProjectLocator {Id = id}; + } + + public static ProjectLocator WithName(string name) + { + return new ProjectLocator {Name = name}; + } + + public string Id { get; set; } + public string Name { get; set; } + + public override string ToString() + { + if (!string.IsNullOrEmpty(Id)) + { + return "id:" + Id; + } + + if (!string.IsNullOrEmpty(Name)) + { + return "name:" + Name; + } + + + var locatorFields = new List(); + + return string.Join(",", locatorFields.ToArray()); + } + } +} diff --git a/src/TeamCitySharp/TeamCityClient.cs b/src/TeamCitySharp/TeamCityClient.cs index eeb9bb82..a3520274 100644 --- a/src/TeamCitySharp/TeamCityClient.cs +++ b/src/TeamCitySharp/TeamCityClient.cs @@ -1,4 +1,4 @@ -using TeamCitySharp.ActionTypes; +using TeamCitySharp.ActionTypes; using TeamCitySharp.Connection; namespace TeamCitySharp @@ -37,8 +37,8 @@ public bool Authenticate() } public IBuilds Builds - { - get { return _builds ?? (_builds = new Builds(_caller)); } + { + get { return _builds ?? (_builds = new Builds(_caller)); } } public IBuildConfigs BuildConfigs @@ -55,8 +55,8 @@ public IServerInformation ServerInformation { get { return _serverInformation ?? (_serverInformation = new ServerInformation(_caller)); } } - - public IUsers Users + + public IUsers Users { get { return _users ?? (_users = new Users(_caller)); } } @@ -72,8 +72,8 @@ public IVcsRoots VcsRoots } public IChanges Changes - { - get { return _changes ?? (_changes = new Changes(_caller)); } + { + get { return _changes ?? (_changes = new Changes(_caller)); } } public IBuildArtifacts Artifacts @@ -81,4 +81,4 @@ public IBuildArtifacts Artifacts get { return _artifacts ?? (_artifacts = new BuildArtifacts(_caller)); } } } -} +} diff --git a/src/TeamCitySharp/TeamCitySharp.csproj b/src/TeamCitySharp/TeamCitySharp.csproj index 2e7df5aa..c91ac5fd 100644 --- a/src/TeamCitySharp/TeamCitySharp.csproj +++ b/src/TeamCitySharp/TeamCitySharp.csproj @@ -33,15 +33,15 @@ 4 - - False - ..\..\packages\EasyHttp.1.6.1.0\lib\net40\EasyHttp.dll + + ..\..\packages\EasyHttp.1.6.67.0\lib\net40\EasyHttp.dll ..\..\packages\JsonFx.2.0.1209.2802\lib\net40\JsonFx.dll + @@ -67,6 +67,10 @@ + + + + diff --git a/src/TeamCitySharp/packages.config b/src/TeamCitySharp/packages.config index eeb961a2..89f56e05 100644 --- a/src/TeamCitySharp/packages.config +++ b/src/TeamCitySharp/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/src/Tests/IntegrationTests/SampleBuildsUsage.cs b/src/Tests/IntegrationTests/SampleBuildsUsage.cs index 152cad5f..5ea8391c 100644 --- a/src/Tests/IntegrationTests/SampleBuildsUsage.cs +++ b/src/Tests/IntegrationTests/SampleBuildsUsage.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Net; +using System.Runtime.CompilerServices; using NUnit.Framework; using TeamCitySharp.Locators; @@ -177,6 +178,19 @@ public void it_returns_all_successful_builds_since_date() Assert.IsNotNull(builds); } + [TestCase("bt5")] + public void it_returns_a_build_from_id(string buildConfigId) + { + var builds = _client.Builds.ByBuildConfigId(buildConfigId); + + Assert.IsTrue(builds.Any(), "There are no builds from config id " + buildConfigId + ". Cannot test retrieving one!"); + + var build = _client.Builds.ByBuildInternalId(builds.First().Id); + + Assert.IsNotNull(build, "Did not return with a build!"); + Assert.IsNotNullOrEmpty(build.Id, "Did not return with a build!"); + } + [Test] public void it_does_not_populate_the_status_text_field_of_the_build_object() { @@ -190,5 +204,18 @@ public void it_does_not_populate_the_status_text_field_of_the_build_object() Assert.That(build.Count == 1); Assert.IsNull(build[0].StatusText); } + + [Test] + public void ig_returns_correct_build_when_calling_by_id() + { + const string buildId = "5726"; + var client = new TeamCityClient("localhost:81"); + client.Connect("admin", "qwerty"); + + var build = client.Builds.ById(buildId); + + Assert.That(build != null); + Assert.That(build.Id == buildId); + } } } diff --git a/src/Tests/IntegrationTests/SampleChangeUsage.cs b/src/Tests/IntegrationTests/SampleChangeUsage.cs index fa8eca06..60239790 100644 --- a/src/Tests/IntegrationTests/SampleChangeUsage.cs +++ b/src/Tests/IntegrationTests/SampleChangeUsage.cs @@ -74,5 +74,13 @@ public void it_returns_change_details_for_build_config(string buildConfigId) Assert.That(changeDetails != null, "Cannot find details of that specified change"); } + + [TestCase("bt113", "42843")] + public void it_returns_change_details_since_build_id(string buildConfigId, string changeId) + { + List changes = _client.Changes.ByBuildConfigIdSinceChangeId(buildConfigId, changeId); + + Assert.That(changes.Any(), "Cannot find any changes since the change id specified"); + } } } \ No newline at end of file diff --git a/src/Tests/IntegrationTests/TeamCitySharp.IntegrationTests.csproj b/src/Tests/IntegrationTests/TeamCitySharp.IntegrationTests.csproj index 95e8426c..4326f56f 100644 --- a/src/Tests/IntegrationTests/TeamCitySharp.IntegrationTests.csproj +++ b/src/Tests/IntegrationTests/TeamCitySharp.IntegrationTests.csproj @@ -78,6 +78,9 @@ TeamCitySharp + + +