コード例 #1
0
        public void Export <T>(string filePath, ExportMetadata metadata, T exportObject)
        {
            var serializedObject = Serializer.Serialize(exportObject.ToDynamic(metadata));

            fileSystem.WriteAllBytes(filePath, Encoding.UTF8.GetBytes(serializedObject));

            log.Debug("Export file {Path} successfully created.", filePath);
        }
コード例 #2
0
        public void Export <T>(string filePath, ExportMetadata metadata, T exportObject)
        {
            var x = exportObject.ToDynamic(metadata);

            var serializerSettings = JsonSerialization.GetDefaultSerializerSettings();
            var serializedObject   = JsonConvert.SerializeObject(x, serializerSettings);

            fileSystem.WriteAllBytes(filePath, Encoding.UTF8.GetBytes(serializedObject));

            log.Debug("Export file {Path} successfully created.", filePath);
        }
コード例 #3
0
 public static dynamic ToDynamic(this object value, ExportMetadata metadata)
 {
     IDictionary<string, object> expando = new ExpandoObject();
     if (value is IEnumerable)
     {
         var items = new List<object>();
         var values = value as IEnumerable;
         foreach (var v in values)
         {
             items.Add(GetExpandoObject(v));
         }
         expando.Add("Items", items);
         expando.Add("$Meta", metadata);
     }
     else
     {
         expando = GetExpandoObject(value);
         expando.Add("$Meta", metadata);
     }
     return expando;
 }
コード例 #4
0
        protected override async Task Export(Dictionary <string, string> paramDictionary)
        {
            if (string.IsNullOrWhiteSpace(paramDictionary["Project"]))
            {
                throw new CommandException("Please specify the project name using the parameter: --project=XYZ");
            }
            if (string.IsNullOrWhiteSpace(paramDictionary["ReleaseVersion"]))
            {
                throw new CommandException("Please specify the release, or range of releases using the parameter: --releaseVersion=1.0.0 for a single release, or --releaseVersion=1.0.0-1.0.3 for a range of releases");
            }
            var projectName    = paramDictionary["Project"];
            var releaseVersion = paramDictionary["ReleaseVersion"];

            Log.Debug("Finding project: {Project:l}", projectName);
            var project = await Repository.Projects.FindByName(projectName).ConfigureAwait(false);

            if (project == null)
            {
                throw new CouldNotFindException("a project named", projectName);
            }

            SemanticVersion minVersionToExport;
            SemanticVersion maxVersionToExport;

            // I don't think -> works on the command line unless it is quoted --releaseVersion="1.0.0->1.0.1"
            if (releaseVersion.IndexOf("->", StringComparison.Ordinal) > 0)
            {
                var releaseVersions = releaseVersion.Split(new[] { "->" }, StringSplitOptions.RemoveEmptyEntries);
                if (releaseVersions.Count() > 2)
                {
                    throw new CommandException("Incorrect format for exporting multiple releases, please specify the release versions as --releaseVersion=1.0.0-1.0.3");
                }
                minVersionToExport = SemanticVersion.Parse(releaseVersions[0]);
                maxVersionToExport = SemanticVersion.Parse(releaseVersions[1]);
            }
            else if (releaseVersion.IndexOf("-", StringComparison.Ordinal) > 0)
            {
                var releaseVersions = releaseVersion.Split(new[] { '-' }, StringSplitOptions.RemoveEmptyEntries);
                if (releaseVersions.Count() > 2)
                {
                    throw new CommandException("Incorrect format for exporting multiple releases, please specify the release versions as --releaseVersion=1.0.0-1.0.3");
                }

                minVersionToExport = SemanticVersion.Parse(releaseVersions[0]);
                if (!SemanticVersion.TryParse(releaseVersions[1], out maxVersionToExport))
                {
                    minVersionToExport = SemanticVersion.Parse(releaseVersion);
                    maxVersionToExport = minVersionToExport;
                }
            }
            else
            {
                minVersionToExport = SemanticVersion.Parse(releaseVersion);
                maxVersionToExport = minVersionToExport;
            }

            Log.Debug("Finding releases for project...");
            var releasesToExport = new List <ReleaseResource>();
            var releases         = await Repository.Projects.GetReleases(project).ConfigureAwait(false);

            await releases.Paginate(Repository, page =>
            {
                foreach (var release in page.Items)
                {
                    var version = SemanticVersion.Parse(release.Version);
                    if (minVersionToExport <= version && version <= maxVersionToExport)
                    {
                        Log.Debug("Found release {Version:l}", version);
                        releasesToExport.Add(release);

                        if (minVersionToExport == maxVersionToExport)
                        {
                            break;
                        }
                    }
                }

                // Stop paging if the range is a single version, or if there is only a single release worth exporting after this page
                return((minVersionToExport != maxVersionToExport) || releasesToExport.Count != 1);
            })
            .ConfigureAwait(false);

            var metadata = new ExportMetadata
            {
                ExportedAt     = DateTime.Now,
                OctopusVersion = (await Repository.LoadRootDocument().ConfigureAwait(false)).Version,
                Type           = typeof(ReleaseExporter).GetAttributeValue((ExporterAttribute ea) => ea.Name),
                ContainerType  = typeof(ReleaseExporter).GetAttributeValue((ExporterAttribute ea) => ea.EntityType)
            };

            FileSystemExporter.Export(FilePath, metadata, releasesToExport);
        }
コード例 #5
0
        protected override async Task Export(Dictionary <string, string> parameters)
        {
            if (string.IsNullOrWhiteSpace(parameters["Name"]))
            {
                throw new CommandException("Please specify the name of the project to export using the parameter: --name=XYZ");
            }

            var projectName = parameters["Name"];

            Log.Debug("Finding project: {Project:l}", projectName);
            var project = await Repository.Projects.FindByName(projectName).ConfigureAwait(false);

            if (project == null)
            {
                throw new CouldNotFindException("a project named", projectName);
            }

            Log.Debug("Finding project group for project");
            var projectGroup = await Repository.ProjectGroups.Get(project.ProjectGroupId).ConfigureAwait(false);

            if (projectGroup == null)
            {
                throw new CouldNotFindException("project group for project", project.Name);
            }

            Log.Debug("Finding variable set for project");
            var variables = await Repository.VariableSets.Get(project.VariableSetId).ConfigureAwait(false);

            if (variables == null)
            {
                throw new CouldNotFindException("variable set for project", project.Name);
            }

            var channelLifecycles = new List <ReferenceDataItem>();
            var channels          = new ChannelResource[0];

            if (Repository.SupportsChannels())
            {
                Log.Debug("Finding channels for project");
                var firstChannelPage = await Repository.Projects.GetChannels(project).ConfigureAwait(false);

                channels = (await firstChannelPage.GetAllPages(Repository).ConfigureAwait(false)).ToArray();

                foreach (var channel in channels.ToArray())
                {
                    if (channel.LifecycleId != null)
                    {
                        var channelLifecycle = await Repository.Lifecycles.Get(channel.LifecycleId).ConfigureAwait(false);

                        if (channelLifecycle == null)
                        {
                            throw new CouldNotFindException("Lifecycle for channel", channel.Name);
                        }
                        if (channelLifecycles.All(cl => cl.Id != channelLifecycle.Id))
                        {
                            channelLifecycles.Add(new ReferenceDataItem(channelLifecycle.Id, channelLifecycle.Name));
                        }
                    }
                }
            }

            Log.Debug("Finding deployment process for project");
            var deploymentProcess = await Repository.DeploymentProcesses.Get(project.DeploymentProcessId).ConfigureAwait(false);

            if (deploymentProcess == null)
            {
                throw new CouldNotFindException("deployment process for project", project.Name);
            }

            Log.Debug("Finding NuGet feed for deployment process...");
            var nugetFeeds = new List <ReferenceDataItem>();

            foreach (var step in deploymentProcess.Steps)
            {
                foreach (var action in step.Actions)
                {
                    PropertyValueResource nugetFeedId;
                    if (action.Properties.TryGetValue("Octopus.Action.Package.NuGetFeedId", out nugetFeedId))
                    {
                        Log.Debug("Finding NuGet feed for step {StepName:l}", step.Name);
                        FeedResource feed = null;
                        if (FeedCustomExpressionHelper.IsRealFeedId(nugetFeedId.Value))
                        {
                            feed = await Repository.Feeds.Get(nugetFeedId.Value).ConfigureAwait(false);
                        }
                        else
                        {
                            feed = FeedCustomExpressionHelper.CustomExpressionFeedWithId(nugetFeedId.Value);
                        }

                        if (feed == null)
                        {
                            throw new CouldNotFindException("NuGet feed for step", step.Name);
                        }

                        if (nugetFeeds.All(f => f.Id != nugetFeedId.Value))
                        {
                            nugetFeeds.Add(new ReferenceDataItem(feed.Id, feed.Name));
                        }
                    }
                }
            }

            Log.Debug("Finding action templates for project");
            var actionTemplates = new List <ReferenceDataItem>();

            foreach (var step in deploymentProcess.Steps)
            {
                foreach (var action in step.Actions)
                {
                    PropertyValueResource templateId;
                    if (action.Properties.TryGetValue("Octopus.Action.Template.Id", out templateId))
                    {
                        Log.Debug("Finding action template for step {StepName:l}", step.Name);
                        var template = await actionTemplateRepository.Get(templateId.Value).ConfigureAwait(false);

                        if (template == null)
                        {
                            throw new CouldNotFindException("action template for step", step.Name);
                        }
                        if (actionTemplates.All(t => t.Id != templateId.Value))
                        {
                            actionTemplates.Add(new ReferenceDataItem(template.Id, template.Name));
                        }
                    }
                }
            }

            var libraryVariableSets = new List <ReferenceDataItem>();

            foreach (var libraryVariableSetId in project.IncludedLibraryVariableSetIds)
            {
                var libraryVariableSet = await Repository.LibraryVariableSets.Get(libraryVariableSetId).ConfigureAwait(false);

                if (libraryVariableSet == null)
                {
                    throw new CouldNotFindException("library variable set with Id", libraryVariableSetId);
                }
                libraryVariableSets.Add(new ReferenceDataItem(libraryVariableSet.Id, libraryVariableSet.Name));
            }

            LifecycleResource lifecycle = null;

            if (project.LifecycleId != null)
            {
                lifecycle = await Repository.Lifecycles.Get(project.LifecycleId).ConfigureAwait(false);

                if (lifecycle == null)
                {
                    throw new CouldNotFindException($"lifecycle with Id {project.LifecycleId} for project ", project.Name);
                }
            }

            var export = new ProjectExport
            {
                Project             = project,
                ProjectGroup        = new ReferenceDataItem(projectGroup.Id, projectGroup.Name),
                VariableSet         = variables,
                DeploymentProcess   = deploymentProcess,
                NuGetFeeds          = nugetFeeds,
                ActionTemplates     = actionTemplates,
                LibraryVariableSets = libraryVariableSets,
                Lifecycle           = lifecycle != null ? new ReferenceDataItem(lifecycle.Id, lifecycle.Name) : null,
                Channels            = channels.ToList(),
                ChannelLifecycles   = channelLifecycles,
            };

            var metadata = new ExportMetadata
            {
                ExportedAt     = DateTime.Now,
                OctopusVersion = Repository.Client.RootDocument.Version,
                Type           = typeof(ProjectExporter).GetAttributeValue((ExporterAttribute ea) => ea.Name),
                ContainerType  = typeof(ProjectExporter).GetAttributeValue((ExporterAttribute ea) => ea.EntityType)
            };

            FileSystemExporter.Export(FilePath, metadata, export);
        }
コード例 #6
0
        protected override void Export(Dictionary<string, string> parameters)
        {
            if (string.IsNullOrWhiteSpace(parameters["Name"]))
            {
                throw new CommandException("Please specify the name of the project to export using the paramater: --name=XYZ");
            }

            var projectName = parameters["Name"];

            Log.Debug("Finding project: " + projectName);
            var project = Repository.Projects.FindByName(projectName);
            if (project == null)
                throw new CouldNotFindException("a project named", projectName);

            Log.Debug("Finding project group for project");
            var projectGroup = Repository.ProjectGroups.Get(project.ProjectGroupId);
            if (projectGroup == null)
                throw new CouldNotFindException("project group for project", project.Name);

            Log.Debug("Finding variable set for project");
            var variables = Repository.VariableSets.Get(project.VariableSetId);
            if (variables == null)
                throw new CouldNotFindException("variable set for project", project.Name);

            var channels = new List<ChannelResource>();
            var channelLifecycles = new List<ReferenceDataItem>();
            if (new SemanticVersion(Repository.Client.RootDocument.Version) >= new SemanticVersion(3, 2, 0, 0))
            {
                Log.Debug("Finding channels for project");
                channels.AddRange(Repository.Projects.GetChannels(project).Items);
                foreach (var channel in channels)
                {
                    if (channel.LifecycleId != null)
                    {
                        var channelLifecycle = Repository.Lifecycles.Get(channel.LifecycleId);
                        if (channelLifecycle == null)
                            throw new CouldNotFindException("Lifecycle for channel", channel.Name);
                        if (channelLifecycles.All(cl => cl.Id != channelLifecycle.Id))
                        {
                            channelLifecycles.Add(new ReferenceDataItem(channelLifecycle.Id, channelLifecycle.Name));
                        }
                    }
                }
            }

            Log.Debug("Finding deployment process for project");
            var deploymentProcess = Repository.DeploymentProcesses.Get(project.DeploymentProcessId);
            if (deploymentProcess == null)
                throw new CouldNotFindException("deployment process for project",project.Name);

            Log.Debug("Finding NuGet feed for deployment process...");
            var nugetFeeds = new List<ReferenceDataItem>();
            foreach (var step in deploymentProcess.Steps)
            {
                foreach (var action in step.Actions)
                {
                    PropertyValueResource nugetFeedId;
                    if (action.Properties.TryGetValue("Octopus.Action.Package.NuGetFeedId", out nugetFeedId))
                    {
                        Log.Debug("Finding NuGet feed for step " + step.Name);
                        FeedResource feed = null;
                        if (FeedCustomExpressionHelper.IsRealFeedId(nugetFeedId.Value))
                            feed = Repository.Feeds.Get(nugetFeedId.Value);
                        else
                            feed = FeedCustomExpressionHelper.CustomExpressionFeedWithId(nugetFeedId.Value);

                        if (feed == null)
                            throw new CouldNotFindException("NuGet feed for step", step.Name);

                        if (nugetFeeds.All(f => f.Id != nugetFeedId.Value))
                        {
                            nugetFeeds.Add(new ReferenceDataItem(feed.Id, feed.Name));
                        }
                    }
                }
            }

            Log.Debug("Finding action templates for project");
            var actionTemplates = new List<ReferenceDataItem>();
            foreach (var step in deploymentProcess.Steps)
            {
                foreach (var action in step.Actions)
                {
                    PropertyValueResource templateId;
                    if (action.Properties.TryGetValue("Octopus.Action.Template.Id", out templateId))
                    {
                        Log.Debug("Finding action template for step " + step.Name);
                        var template = actionTemplateRepository.Get(templateId.Value);
                        if (template == null)
                            throw new CouldNotFindException("action template for step", step.Name);
                        if (actionTemplates.All(t => t.Id != templateId.Value))
                        {
                            actionTemplates.Add(new ReferenceDataItem(template.Id, template.Name));
                        }
                    }
                }
            }

            var libraryVariableSets = new List<ReferenceDataItem>();
            foreach (var libraryVariableSetId in project.IncludedLibraryVariableSetIds)
            {
                var libraryVariableSet = Repository.LibraryVariableSets.Get(libraryVariableSetId);
                if (libraryVariableSet == null)
                {
                    throw new CouldNotFindException("library variable set with Id", libraryVariableSetId);
                }
                libraryVariableSets.Add(new ReferenceDataItem(libraryVariableSet.Id, libraryVariableSet.Name));
            }

            LifecycleResource lifecycle = null;
            if (project.LifecycleId != null)
            {
                lifecycle = Repository.Lifecycles.Get(project.LifecycleId);
                if (lifecycle == null)
                {
                    throw new CouldNotFindException("lifecycle with Id " + project.LifecycleId + " for project ", project.Name);
                }
            }
            
            var export = new ProjectExport
            {
                Project = project,
                ProjectGroup = new ReferenceDataItem(projectGroup.Id, projectGroup.Name),
                VariableSet = variables,
                DeploymentProcess = deploymentProcess,
                NuGetFeeds = nugetFeeds,
                ActionTemplates = actionTemplates,
                LibraryVariableSets = libraryVariableSets,
                Lifecycle = lifecycle != null ? new ReferenceDataItem(lifecycle.Id, lifecycle.Name) : null,
                Channels = channels.ToList(),
                ChannelLifecycles = channelLifecycles,
            };

            var metadata = new ExportMetadata
            {
                ExportedAt = DateTime.Now,
                OctopusVersion = Repository.Client.RootDocument.Version,
                Type = typeof (ProjectExporter).GetAttributeValue((ExporterAttribute ea) => ea.Name),
                ContainerType = typeof (ProjectExporter).GetAttributeValue((ExporterAttribute ea) => ea.EntityType)
            };
            FileSystemExporter.Export(FilePath, metadata, export);
        }
コード例 #7
0
        protected override void Export(Dictionary <string, string> paramDictionary)
        {
            if (string.IsNullOrWhiteSpace(paramDictionary["Project"]))
            {
                throw new CommandException("Please specify the project name using the parameter: --project=XYZ");
            }
            if (string.IsNullOrWhiteSpace(paramDictionary["ReleaseVersion"]))
            {
                throw new CommandException("Please specify the release, or range of releases using the parameter: --releaseVersion=1.0.0 for a single release, or --releaseVersion=1.0.0->1.0.3 for a range of releases");
            }
            var projectName    = paramDictionary["Project"];
            var releaseVersion = paramDictionary["ReleaseVersion"];

            Log.Debug("Finding project: " + projectName);
            var project = Repository.Projects.FindByName(projectName);

            if (project == null)
            {
                throw new CouldNotFindException("a project named", projectName);
            }

            Log.Debug("Finding releases for project...");
            var releases = Repository.Projects.GetReleases(project);

            var             releasesToExport = new List <ReleaseResource>();
            SemanticVersion minVersionToExport;
            SemanticVersion maxVersionToExport;

            if (releaseVersion.IndexOf("->", StringComparison.Ordinal) > 0)
            {
                var releaseVersions = releaseVersion.Split(new[] { "->" }, StringSplitOptions.RemoveEmptyEntries);
                if (releaseVersions.Count() > 2)
                {
                    throw new CommandException("Incorrect format for exporting multiple releases, please specify the release versions as 1.0.0->1.0.3");
                }
                minVersionToExport = SemanticVersion.Parse(releaseVersions[0]);
                maxVersionToExport = SemanticVersion.Parse(releaseVersions[1]);
            }
            else if (releaseVersion.IndexOf("-", StringComparison.Ordinal) > 0)
            {
                var releaseVersions = releaseVersion.Split(new[] { '-' }, StringSplitOptions.RemoveEmptyEntries);
                if (releaseVersions.Count() > 2)
                {
                    throw new CommandException("Incorrect format for exporting multiple releases, please specify the release versions as 1.0.0-1.0.3");
                }

                minVersionToExport = SemanticVersion.Parse(releaseVersions[0]);
                if (!SemanticVersion.TryParse(releaseVersions[1], out maxVersionToExport))
                {
                    minVersionToExport = SemanticVersion.Parse(releaseVersion);
                    maxVersionToExport = minVersionToExport;
                }
            }
            else
            {
                minVersionToExport = SemanticVersion.Parse(releaseVersion);
                maxVersionToExport = minVersionToExport;
            }

            while (releases.Items.Count > 0)
            {
                foreach (var release in releases.Items)
                {
                    var version = SemanticVersion.Parse(release.Version);
                    if (minVersionToExport <= version && version <= maxVersionToExport)
                    {
                        Log.Debug("Found release " + version);
                        releasesToExport.Add(release);

                        if (minVersionToExport == maxVersionToExport)
                        {
                            break;
                        }
                    }
                }

                if (((minVersionToExport == maxVersionToExport) && releasesToExport.Count == 1) || !releases.HasLink("Page.Next"))
                {
                    break;
                }

                releases = Repository.Client.List <ReleaseResource>(releases.Link("Page.Next"));
            }

            var metadata = new ExportMetadata
            {
                ExportedAt     = DateTime.Now,
                OctopusVersion = Repository.Client.RootDocument.Version,
                Type           = typeof(ReleaseExporter).GetAttributeValue((ExporterAttribute ea) => ea.Name),
                ContainerType  = typeof(ReleaseExporter).GetAttributeValue((ExporterAttribute ea) => ea.EntityType)
            };

            FileSystemExporter.Export(FilePath, metadata, releasesToExport);
        }
コード例 #8
0
        protected override async Task Export(Dictionary<string, string> paramDictionary)
        {
            if (string.IsNullOrWhiteSpace(paramDictionary["Project"])) throw new CommandException("Please specify the project name using the parameter: --project=XYZ");
            if (string.IsNullOrWhiteSpace(paramDictionary["ReleaseVersion"])) throw new CommandException("Please specify the release, or range of releases using the parameter: --releaseVersion=1.0.0 for a single release, or --releaseVersion=1.0.0-1.0.3 for a range of releases");
            var projectName = paramDictionary["Project"];
            var releaseVersion = paramDictionary["ReleaseVersion"];

            Log.Debug("Finding project: {Project:l}", projectName);
            var project = await Repository.Projects.FindByName(projectName).ConfigureAwait(false);
            if (project == null)
                throw new CouldNotFindException("a project named", projectName);

            SemanticVersion minVersionToExport;
            SemanticVersion maxVersionToExport;

            // I don't think -> works on the command line unless it is quoted --releaseVersion="1.0.0->1.0.1"
            if (releaseVersion.IndexOf("->", StringComparison.Ordinal) > 0)
            {
                var releaseVersions = releaseVersion.Split(new[] { "->" }, StringSplitOptions.RemoveEmptyEntries);
                if (releaseVersions.Count() > 2)
                    throw new CommandException("Incorrect format for exporting multiple releases, please specify the release versions as --releaseVersion=1.0.0-1.0.3");
                minVersionToExport = SemanticVersion.Parse(releaseVersions[0]);
                maxVersionToExport = SemanticVersion.Parse(releaseVersions[1]);
            }
            else if (releaseVersion.IndexOf("-", StringComparison.Ordinal) > 0)
            {
                var releaseVersions = releaseVersion.Split(new[] {'-'}, StringSplitOptions.RemoveEmptyEntries);
                if (releaseVersions.Count() > 2)
                    throw new CommandException("Incorrect format for exporting multiple releases, please specify the release versions as --releaseVersion=1.0.0-1.0.3");

                minVersionToExport = SemanticVersion.Parse(releaseVersions[0]);
                if (!SemanticVersion.TryParse(releaseVersions[1], out maxVersionToExport))
                {
                    minVersionToExport = SemanticVersion.Parse(releaseVersion);
                    maxVersionToExport = minVersionToExport;
                }
            }
            else
            {
                minVersionToExport = SemanticVersion.Parse(releaseVersion);
                maxVersionToExport = minVersionToExport;
            }

            Log.Debug("Finding releases for project...");
            var releasesToExport = new List<ReleaseResource>();
            var releases = await Repository.Projects.GetReleases(project).ConfigureAwait(false);
            await releases.Paginate(Repository, page =>
            {
                foreach (var release in page.Items)
                {
                    var version = SemanticVersion.Parse(release.Version);
                    if (minVersionToExport <= version && version <= maxVersionToExport)
                    {
                        Log.Debug("Found release {Version:l}", version);
                        releasesToExport.Add(release);

                        if (minVersionToExport == maxVersionToExport)
                        {
                            break;
                        }
                    }
                }

                // Stop paging if the range is a single version, or if there is only a single release worth exporting after this page
                return (minVersionToExport != maxVersionToExport) || releasesToExport.Count != 1;
            })
            .ConfigureAwait(false);

            var metadata = new ExportMetadata
            {
                ExportedAt = DateTime.Now,
                OctopusVersion = Repository.Client.RootDocument.Version,
                Type = typeof (ReleaseExporter).GetAttributeValue((ExporterAttribute ea) => ea.Name),
                ContainerType = typeof (ReleaseExporter).GetAttributeValue((ExporterAttribute ea) => ea.EntityType)
            };
            FileSystemExporter.Export(FilePath, metadata, releasesToExport);
        }
コード例 #9
0
        protected override void Export(Dictionary<string, string> paramDictionary)
        {
            if (string.IsNullOrWhiteSpace(paramDictionary["Project"])) throw new CommandException("Please specify the project name using the parameter: --project=XYZ");
            if (string.IsNullOrWhiteSpace(paramDictionary["ReleaseVersion"])) throw new CommandException("Please specify the release, or range of releases using the parameter: --releaseVersion=1.0.0 for a single release, or --releaseVersion=1.0.0->1.0.3 for a range of releases");
            var projectName = paramDictionary["Project"];
            var releaseVersion = paramDictionary["ReleaseVersion"];

            Log.Debug("Finding project: " + projectName);
            var project = Repository.Projects.FindByName(projectName);
            if (project == null)
                throw new CouldNotFindException("a project named", projectName);

            Log.Debug("Finding releases for project...");
            var releases = Repository.Projects.GetReleases(project);

            var releasesToExport = new List<ReleaseResource>();
            SemanticVersion minVersionToExport;
            SemanticVersion maxVersionToExport;

            if (releaseVersion.IndexOf("->", StringComparison.Ordinal) > 0)
            {
                var releaseVersions = releaseVersion.Split(new[] { "->" }, StringSplitOptions.RemoveEmptyEntries);
                if (releaseVersions.Count() > 2)
                    throw new CommandException("Incorrect format for exporting multiple releases, please specify the release versions as 1.0.0->1.0.3");
                minVersionToExport = SemanticVersion.Parse(releaseVersions[0]);
                maxVersionToExport = SemanticVersion.Parse(releaseVersions[1]);
            }
            else if (releaseVersion.IndexOf("-", StringComparison.Ordinal) > 0)
            {
                var releaseVersions = releaseVersion.Split(new[] {'-'}, StringSplitOptions.RemoveEmptyEntries);
                if (releaseVersions.Count() > 2)
                    throw new CommandException("Incorrect format for exporting multiple releases, please specify the release versions as 1.0.0-1.0.3");

                minVersionToExport = SemanticVersion.Parse(releaseVersions[0]);
                if (!SemanticVersion.TryParse(releaseVersions[1], out maxVersionToExport))
                {
                    minVersionToExport = SemanticVersion.Parse(releaseVersion);
                    maxVersionToExport = minVersionToExport;
                }
            }
            else
            {
                minVersionToExport = SemanticVersion.Parse(releaseVersion);
                maxVersionToExport = minVersionToExport;
            }

            while (releases.Items.Count > 0)
            {
                foreach (var release in releases.Items)
                {
                    var version = SemanticVersion.Parse(release.Version);
                    if (minVersionToExport <= version && version <= maxVersionToExport)
                    {
                        Log.Debug("Found release " + version);
                        releasesToExport.Add(release);

                        if (minVersionToExport == maxVersionToExport)
                        {
                            break;
                        }
                    }
                }

                if (((minVersionToExport == maxVersionToExport) && releasesToExport.Count == 1) || !releases.HasLink("Page.Next"))
                {
                    break;
                }

                releases = Repository.Client.List<ReleaseResource>(releases.Link("Page.Next"));
            }

            var metadata = new ExportMetadata
            {
                ExportedAt = DateTime.Now,
                OctopusVersion = Repository.Client.RootDocument.Version,
                Type = typeof (ReleaseExporter).GetAttributeValue((ExporterAttribute ea) => ea.Name),
                ContainerType = typeof (ReleaseExporter).GetAttributeValue((ExporterAttribute ea) => ea.EntityType)
            };
            FileSystemExporter.Export(FilePath, metadata, releasesToExport);
        }