Пример #1
0
        public AddOnFrameworkWindow()
        {
            // set Caption property (not Title), since Title is managed internally to properly combine selected Tab Header and Caption for display in the windows taskbar
            // This is the name displayed in the top-left of the window
            Caption = "AddOn Framework";

            // Set the default dimensions of the window
            Width  = 1085;
            Height = 900;

            // TabControl should be created for window content if tab features are wanted
            TabControl tc = new TabControl();

            // Attached properties defined in TabControlManager class should be set to achieve tab moving, adding/removing tabs
            TabControlManager.SetIsMovable(tc, true);
            TabControlManager.SetCanAddTabs(tc, true);
            TabControlManager.SetCanRemoveTabs(tc, true);

            // if ability to add new tabs is desired, TabControl has to have attached property "Factory" set.
            TabControlManager.SetFactory(tc, new AddOnFrameworkWindowFactory());
            Content = tc;

            /* In order to have link buttons functionality, tab control items must be derived from Tools.NTTabPage
             * They can be added using extention method AddNTTabPage(NTTabPage page) */
            tc.AddNTTabPage(new NinjaTraderAddOnProject.AddOnPage());

            // WorkspaceOptions property must be set
            Loaded += (o, e) =>
            {
                if (WorkspaceOptions == null)
                {
                    WorkspaceOptions = new WorkspaceOptions("AddOnFramework-" + Guid.NewGuid().ToString("N"), this);
                }
            };
        }
Пример #2
0
        /// <summary>
        /// Class for a workspace. This is a data structure tha contains blocks.
        /// There is no UI,and can be created headlessly.
        /// </summary>
        public Workspace(WorkspaceOptions options = null, string optId = null)
        {
            if (string.IsNullOrEmpty(optId))
            {
                Id = Utils.GenUid();
            }
            else
            {
                Id = optId;
            }

            if (mWorkspaceDB.ContainsKey(Id))
            {
                mWorkspaceDB[Id] = this;
                Debug.LogWarning("Already contains workspace id:" + Id);
            }
            else
            {
                mWorkspaceDB.Add(Id, this);
            }

            Options = options ?? new WorkspaceOptions();

            TopBlocks        = new List <Block>();
            BlockDB          = new Dictionary <string, Block>();
            VariableMap      = new VariableMap(this);
            ConnectionDBList = ConnectionDB.Build();
            ProcedureDB      = new ProcedureDB(this);
        }
Пример #3
0
 public PhotoDirectoryLoader(IFileSystem fileSystem, IDataSerializer serializer, IAppDbContextOptionsBuilder contextBuilder,
                             IOptions <WorkspaceOptions> workspaceOptions)
 {
     _fileSystem       = fileSystem;
     _serializer       = serializer;
     _workspaceOptions = workspaceOptions.Value;
     _contextBuilder   = contextBuilder;
 }
Пример #4
0
 static void RunWorkspaceTasks(WorkspaceOptions opts)
 {
     if (opts.Get)
     {
         var workspaces = workspaceApi.getWorkspaces(Email.From(opts.Username), Password.From(opts.Password),
                                                     resetEvent);
         CliPresenter.present(workspaces.Result);
     }
 }
Пример #5
0
        /*
         * This is the constructor for the new NTWindow.
         * This document sets up the basic window before it gets displayed.
         * This also defines what TabPage will be used and the Window Factory that will be used in the window creation process.
         * This document is also where you would set Tab defaults like if this window will have a tab control, if the tabs are movable etc..
         */
        public AddonShellWindow()
        {
            // set Caption property (not Title), since Title is managed internally to properly combine selected Tab Header and Caption for display in the windows taskbar
            // This is the name displayed in the top-left of the window
            Caption = "Addon Shell Window";

            // Set the default dimensions of the window
            //Width = 800;
            //Height = 600;

            // TabControl should be created for window content if tab features are wanted
            TabControl tabControl = new TabControl();

            // Attached properties defined in TabControlManager class should be set to achieve tab moving, adding/removing tabs
            TabControlManager.SetIsMovable(tabControl, false);
            TabControlManager.SetCanAddTabs(tabControl, false);
            TabControlManager.SetCanRemoveTabs(tabControl, false);

            // if ability to add new tabs is desired, TabControl has to have attached property "Factory" set.
            TabControlManager.SetFactory(tabControl, new AddonShellWindowFactory());
            Content = tabControl;

            /* In order to have link buttons functionality, tab control items must be derived from Tools.NTTabPage
             * They can be added using extention method AddNTTabPage(NTTabPage page) */
            //tabControl.AddNTTabPage(new AddonShellWindowTabPage());
            tabControl.AddNTTabPage(new NinjaTrader.NinjaScript.AddOns.AddonShellWindow());

            // WorkspaceOptions property must be set
            // This is a inline Window Loaded handler, once the window loads, if the WorkspaceOptions are not present,
            // a new WorkspaceOptions object is created for this window using its GUID.
            Loaded += (o, e) =>
            {
                if (WorkspaceOptions == null)
                {
                    WorkspaceOptions = new WorkspaceOptions("AddonShellWindow" + Guid.NewGuid().ToString("N"), this);
                }
            };
        }
        public TrackingConfig PrepareDirectory(
            IExecutionContext executionContext,
            IList <RepositoryResource> repositories,
            WorkspaceOptions workspace)
        {
            // Validate parameters.
            Trace.Entering();
            ArgUtil.NotNull(executionContext, nameof(executionContext));
            ArgUtil.NotNull(executionContext.Variables, nameof(executionContext.Variables));
            ArgUtil.NotNull(repositories, nameof(repositories));

            var trackingManager = HostContext.GetService <ITrackingManager>();

            // Create the tracking config for this execution of the pipeline
            var agentSettings = HostContext.GetService <IConfigurationStore>().GetSettings();
            var newConfig     = trackingManager.Create(executionContext, repositories, ShouldOverrideBuildDirectory(repositories, agentSettings));

            // Load the tracking config from the last execution of the pipeline
            var existingConfig = trackingManager.LoadExistingTrackingConfig(executionContext);

            // If there aren't any major changes, merge the configurations and use the same workspace
            if (trackingManager.AreTrackingConfigsCompatible(executionContext, newConfig, existingConfig))
            {
                newConfig = trackingManager.MergeTrackingConfigs(executionContext, newConfig, existingConfig);
            }
            else if (existingConfig != null)
            {
                // If the previous config had different repos, get a new workspace folder and mark the old one for clean up
                trackingManager.MarkForGarbageCollection(executionContext, existingConfig);

                // If the config file was updated to a new config, we need to delete the legacy artifact/staging directories.
                // DeleteDirectory will check for the existence of the folders first.
                DeleteDirectory(
                    executionContext,
                    description: "legacy artifacts directory",
                    path: Path.Combine(existingConfig.BuildDirectory, Constants.Build.Path.LegacyArtifactsDirectory));
                DeleteDirectory(
                    executionContext,
                    description: "legacy staging directory",
                    path: Path.Combine(existingConfig.BuildDirectory, Constants.Build.Path.LegacyStagingDirectory));
            }

            // Save any changes to the config file
            trackingManager.UpdateTrackingConfig(executionContext, newConfig);

            // Prepare the build directory.
            // There are 2 ways to provide build directory clean policy.
            //     1> set definition variable build.clean or agent.clean.buildDirectory. (on-prem user need to use this, since there is no Web UI in TFS 2016)
            //     2> select source clean option in definition repository tab. (VSTS will have this option in definition designer UI)
            BuildCleanOption cleanOption = GetBuildDirectoryCleanOption(executionContext, workspace);

            CreateDirectory(
                executionContext,
                description: "build directory",
                path: Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Work), newConfig.BuildDirectory),
                deleteExisting: cleanOption == BuildCleanOption.All);
            CreateDirectory(
                executionContext,
                description: "artifacts directory",
                path: Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Work), newConfig.ArtifactsDirectory),
                deleteExisting: true);
            CreateDirectory(
                executionContext,
                description: "test results directory",
                path: Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Work), newConfig.TestResultsDirectory),
                deleteExisting: true);
            CreateDirectory(
                executionContext,
                description: "binaries directory",
                path: Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Work), newConfig.BuildDirectory, Constants.Build.Path.BinariesDirectory),
                deleteExisting: cleanOption == BuildCleanOption.Binary);

            var defaultSourceDirectory = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Work), newConfig.SourcesDirectory);

            CreateDirectory(
                executionContext,
                description: "source directory",
                path: defaultSourceDirectory,
                deleteExisting: cleanOption == BuildCleanOption.Source);

            // Set the default clone path for each repository (the Checkout task may override this later)
            foreach (var repository in repositories)
            {
                String repoPath;
                if (RepositoryUtil.HasMultipleCheckouts(executionContext.JobSettings))
                {
                    // If we have multiple checkouts they should all be rooted to the sources directory (_work/1/s/repo1)
                    var repoSourceDirectory = newConfig?.RepositoryTrackingInfo.Where(item => string.Equals(item.Identifier, repository.Alias, StringComparison.OrdinalIgnoreCase)).Select(item => item.SourcesDirectory).FirstOrDefault();
                    if (repoSourceDirectory != null)
                    {
                        repoPath = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Work), repoSourceDirectory);
                    }
                    else
                    {
                        repoPath = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Work), newConfig.SourcesDirectory, RepositoryUtil.GetCloneDirectory(repository));
                    }
                }
                else
                {
                    // For single checkouts, the repository is rooted to the sources folder (_work/1/s)
                    repoPath = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Work), newConfig.SourcesDirectory);
                }

                if (!string.Equals(repoPath, defaultSourceDirectory, StringComparison.Ordinal))
                {
                    CreateDirectory(
                        executionContext,
                        description: "repository source directory",
                        path: repoPath,
                        deleteExisting: cleanOption == BuildCleanOption.Source);
                }

                Trace.Info($"Set repository path for repository {repository.Alias} to '{repoPath}'");
                repository.Properties.Set <string>(RepositoryPropertyNames.Path, repoPath);
            }

            return(newConfig);
        }
        // Prefer variable over endpoint data when get build directory clean option.
        // Prefer agent.clean.builddirectory over build.clean when use variable
        // available value for build.clean or agent.clean.builddirectory:
        //      Delete entire build directory if build.clean=all is set.
        //      Recreate binaries dir if clean=binary is set.
        //      Recreate source dir if clean=src is set.
        private BuildCleanOption GetBuildDirectoryCleanOption(IExecutionContext executionContext, WorkspaceOptions workspace)
        {
            BuildCleanOption?cleanOption = executionContext.Variables.Build_Clean;

            if (cleanOption != null)
            {
                return(cleanOption.Value);
            }

            if (workspace == null)
            {
                return(BuildCleanOption.None);
            }
            else
            {
                Dictionary <string, string> workspaceClean = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);
                workspaceClean["clean"] = workspace.Clean;
                executionContext.Variables.ExpandValues(target: workspaceClean);
                VarUtil.ExpandEnvironmentVariables(HostContext, target: workspaceClean);
                string expandedClean = workspaceClean["clean"];
                if (string.Equals(expandedClean, PipelineConstants.WorkspaceCleanOptions.All, StringComparison.OrdinalIgnoreCase))
                {
                    return(BuildCleanOption.All);
                }
                else if (string.Equals(expandedClean, PipelineConstants.WorkspaceCleanOptions.Resources, StringComparison.OrdinalIgnoreCase))
                {
                    return(BuildCleanOption.Source);
                }
                else if (string.Equals(expandedClean, PipelineConstants.WorkspaceCleanOptions.Outputs, StringComparison.OrdinalIgnoreCase))
                {
                    return(BuildCleanOption.Binary);
                }
                else
                {
                    return(BuildCleanOption.None);
                }
            }
        }
Пример #8
0
        public override void InitializeJobExtension(IExecutionContext executionContext, IList <JobStep> steps, WorkspaceOptions workspace)
        {
            ArgUtil.NotNull(executionContext, nameof(executionContext));
            Trace.Entering();

            executionContext.Output(StringUtil.Loc("PrepareReleasesDir"));
            var directoryManager = HostContext.GetService <IReleaseDirectoryManager>();

            ReleaseId             = executionContext.Variables.GetInt(Constants.Variables.Release.ReleaseId) ?? 0;
            TeamProjectId         = executionContext.Variables.GetGuid(Constants.Variables.System.TeamProjectId) ?? Guid.Empty;
            SkipArtifactsDownload = executionContext.Variables.GetBoolean(Constants.Variables.Release.SkipArtifactsDownload) ?? false;
            string releaseDefinitionName = executionContext.Variables.Get(Constants.Variables.Release.ReleaseDefinitionName);

            // TODO: Should we also write to log in executionContext.Output methods? so that we don't have to repeat writing into logs?
            // Log these values here to debug scenarios where downloading the artifact fails.
            executionContext.Output($"ReleaseId={ReleaseId}, TeamProjectId={TeamProjectId}, ReleaseDefinitionName={releaseDefinitionName}");

            var releaseDefinition = executionContext.Variables.Get(Constants.Variables.Release.ReleaseDefinitionId);

            if (string.IsNullOrEmpty(releaseDefinition))
            {
                string pattern = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars());
                Regex  regex   = new Regex(string.Format("[{0}]", Regex.Escape(pattern)));
                releaseDefinition = regex.Replace(releaseDefinitionName, string.Empty);
            }

            ArgUtil.NotNull(executionContext, nameof(executionContext)); // I am not sure why this is needed, but static analysis flagged all uses of executionContext below this point
            var releaseTrackingConfig = directoryManager.PrepareArtifactsDirectory(
                HostContext.GetDirectory(WellKnownDirectory.Work),
                executionContext.Variables.System_CollectionId,
                executionContext.Variables.System_TeamProjectId.ToString(),
                releaseDefinition);

            ReleaseWorkingFolder = Path.Combine(
                HostContext.GetDirectory(WellKnownDirectory.Work),
                releaseTrackingConfig.ReleaseDirectory);

            ArtifactsWorkingFolder = string.IsNullOrEmpty(executionContext.Variables.Release_ArtifactsDirectory)
                ? Path.Combine(
                HostContext.GetDirectory(WellKnownDirectory.Work),
                releaseTrackingConfig.ReleaseDirectory,
                Constants.Release.Path.ArtifactsDirectory)
                : executionContext.Variables.Release_ArtifactsDirectory;
            executionContext.Output($"Release folder: {ArtifactsWorkingFolder}");

            // Ensure directory exist
            if (!Directory.Exists(ArtifactsWorkingFolder))
            {
                Trace.Info($"Creating {ArtifactsWorkingFolder}.");
                Directory.CreateDirectory(ArtifactsWorkingFolder);
            }

            SetLocalVariables(executionContext, ArtifactsWorkingFolder);

            // Log the environment variables available after populating the variable service with our variables
            LogEnvironmentVariables(executionContext);

            if (SkipArtifactsDownload)
            {
                // If this is the first time the agent is executing a task, we need to create the artifactsFolder
                // otherwise Process.StartWithCreateProcess() will fail with the error "The directory name is invalid"
                // because the working folder doesn't exist
                CreateWorkingFolderIfRequired(executionContext, ArtifactsWorkingFolder);

                // log the message that the user chose to skip artifact download and move on
                executionContext.Output(StringUtil.Loc("RMUserChoseToSkipArtifactDownload"));
                Trace.Info("Skipping artifact download based on the setting specified.");
            }
            else
            {
                ReleaseArtifacts = GetReleaseArtifacts(executionContext);

                if (!ReleaseArtifacts.Any())
                {
                    CreateArtifactsFolder(executionContext, ArtifactsWorkingFolder);
                    Trace.Info("No artifacts found to be downloaded by agent.");
                }
            }

            CheckForAvailableDiskSpace(executionContext);
        }
Пример #9
0
 public override void InitializeJobExtension(IExecutionContext context, IList <JobStep> steps, WorkspaceOptions workspace)
 {
     return;
 }
Пример #10
0
        public TrackingConfig PrepareDirectory(
            IExecutionContext executionContext,
            IList <RepositoryResource> repositories,
            WorkspaceOptions workspace)
        {
            // Validate parameters.
            Trace.Entering();
            ArgUtil.NotNull(executionContext, nameof(executionContext));
            ArgUtil.NotNull(executionContext.Variables, nameof(executionContext.Variables));
            ArgUtil.NotNull(repositories, nameof(repositories));

            // Get the primary repository (self)
            var primaryRepository = RepositoryUtil.GetPrimaryRepository(repositories);

            ArgUtil.NotNull(primaryRepository, nameof(primaryRepository));

            // TODO (next PR): We need to modify the Tracking file to handle multiple repositories (currently we are only tracking the self repo)
            var trackingManager = HostContext.GetService <ITrackingManager>();

            // Defer to the source provider to calculate the hash key.
            Trace.Verbose("Calculating build directory hash key.");
            string hashKey = primaryRepository.GetSourceDirectoryHashKey(executionContext);

            Trace.Verbose($"Hash key: {hashKey}");

            // Load the existing tracking file if one already exists.
            string trackingFile = Path.Combine(
                HostContext.GetDirectory(WellKnownDirectory.Work),
                Constants.Build.Path.SourceRootMappingDirectory,
                executionContext.Variables.System_CollectionId,
                executionContext.Variables.System_DefinitionId,
                Constants.Build.Path.TrackingConfigFile);

            Trace.Verbose($"Loading tracking config if exists: {trackingFile}");
            TrackingConfigBase existingConfig = trackingManager.LoadIfExists(executionContext, trackingFile);

            // Check if the build needs to be garbage collected. If the hash key
            // has changed, then the existing build directory cannot be reused.
            TrackingConfigBase garbageConfig = null;

            if (existingConfig != null &&
                !string.Equals(existingConfig.HashKey, hashKey, StringComparison.OrdinalIgnoreCase))
            {
                // Just store a reference to the config for now. It can safely be
                // marked for garbage collection only after the new build directory
                // config has been created.
                Trace.Verbose($"Hash key from existing tracking config does not match. Existing key: {existingConfig.HashKey}");
                garbageConfig  = existingConfig;
                existingConfig = null;
            }

            // Create a new tracking config if required.
            TrackingConfig newConfig;

            if (existingConfig == null)
            {
                Trace.Verbose("Creating a new tracking config file.");
                var agentSetting = HostContext.GetService <IConfigurationStore>().GetSettings();
                newConfig = trackingManager.Create(
                    executionContext,
                    primaryRepository,
                    hashKey,
                    trackingFile,
                    primaryRepository.TestOverrideBuildDirectory(agentSetting));
                ArgUtil.NotNull(newConfig, nameof(newConfig));
            }
            else
            {
                // Convert legacy format to the new format if required.
                newConfig = ConvertToNewFormat(executionContext, primaryRepository, existingConfig);

                // Fill out repository type if it's not there.
                // repository type is a new property introduced for maintenance job
                if (string.IsNullOrEmpty(newConfig.RepositoryType))
                {
                    newConfig.RepositoryType = primaryRepository.Type;
                }

                // For existing tracking config files, update the job run properties.
                Trace.Verbose("Updating job run properties.");
                trackingManager.UpdateJobRunProperties(executionContext, newConfig, trackingFile);
            }

            // Mark the old configuration for garbage collection.
            if (garbageConfig != null)
            {
                Trace.Verbose("Marking existing config for garbage collection.");
                trackingManager.MarkForGarbageCollection(executionContext, garbageConfig);
            }

            // Prepare the build directory.
            // There are 2 ways to provide build directory clean policy.
            //     1> set definition variable build.clean or agent.clean.buildDirectory. (on-prem user need to use this, since there is no Web UI in TFS 2016)
            //     2> select source clean option in definition repository tab. (VSTS will have this option in definition designer UI)
            BuildCleanOption cleanOption = GetBuildDirectoryCleanOption(executionContext, workspace);

            CreateDirectory(
                executionContext,
                description: "build directory",
                path: Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Work), newConfig.BuildDirectory),
                deleteExisting: cleanOption == BuildCleanOption.All);
            CreateDirectory(
                executionContext,
                description: "artifacts directory",
                path: Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Work), newConfig.ArtifactsDirectory),
                deleteExisting: true);
            CreateDirectory(
                executionContext,
                description: "test results directory",
                path: Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Work), newConfig.TestResultsDirectory),
                deleteExisting: true);
            CreateDirectory(
                executionContext,
                description: "binaries directory",
                path: Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Work), newConfig.BuildDirectory, Constants.Build.Path.BinariesDirectory),
                deleteExisting: cleanOption == BuildCleanOption.Binary);
            CreateDirectory(
                executionContext,
                description: "source directory",
                path: Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Work), newConfig.SourcesDirectory),
                deleteExisting: cleanOption == BuildCleanOption.Source);

            // Set the default clone path for each repository (the Checkout task may override this later)
            foreach (var repository in repositories)
            {
                var repoPath = GetDefaultRepositoryPath(executionContext, repository, newConfig.SourcesDirectory);
                Trace.Info($"Set repository path for repository {repository.Alias} to '{repoPath}'");
                repository.Properties.Set <string>(RepositoryPropertyNames.Path, repoPath);
            }

            return(newConfig);
        }
Пример #11
0
        public TrackingConfig PrepareDirectory(
            IExecutionContext executionContext,
            WorkspaceOptions workspace)
        {
            // Validate parameters.
            Trace.Entering();
            ArgUtil.NotNull(executionContext, nameof(executionContext));
            var trackingManager = HostContext.GetService <ITrackingManager>();

            var repoFullName = executionContext.GetGitHubContext("repository");

            ArgUtil.NotNullOrEmpty(repoFullName, nameof(repoFullName));

            // Load the existing tracking file if one already exists.
            string trackingFile = Path.Combine(
                HostContext.GetDirectory(WellKnownDirectory.Work),
                Constants.Pipeline.Path.PipelineMappingDirectory,
                repoFullName,
                Constants.Pipeline.Path.TrackingConfigFile);

            Trace.Info($"Loading tracking config if exists: {trackingFile}");
            TrackingConfig trackingConfig = trackingManager.LoadIfExists(executionContext, trackingFile);

            // Create a new tracking config if required.
            if (trackingConfig == null)
            {
                Trace.Info("Creating a new tracking config file.");
                trackingConfig = trackingManager.Create(
                    executionContext,
                    trackingFile);
                ArgUtil.NotNull(trackingConfig, nameof(trackingConfig));
            }
            else
            {
                // For existing tracking config files, update the job run properties.
                Trace.Info("Updating job run properties.");
                trackingConfig.LastRunOn = DateTimeOffset.Now;
                trackingManager.Update(executionContext, trackingConfig, trackingFile);
            }

            // Prepare the pipeline directory.
            if (string.Equals(workspace?.Clean, PipelineConstants.WorkspaceCleanOptions.All, StringComparison.OrdinalIgnoreCase))
            {
                CreateDirectory(
                    executionContext,
                    description: "pipeline directory",
                    path: Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Work), trackingConfig.PipelineDirectory),
                    deleteExisting: true);

                CreateDirectory(
                    executionContext,
                    description: "workspace directory",
                    path: Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Work), trackingConfig.WorkspaceDirectory),
                    deleteExisting: true);
            }
            else if (string.Equals(workspace?.Clean, PipelineConstants.WorkspaceCleanOptions.Resources, StringComparison.OrdinalIgnoreCase))
            {
                foreach (var repository in trackingConfig.Repositories)
                {
                    CreateDirectory(
                        executionContext,
                        description: $"directory {repository.Value.RepositoryPath} for repository {repository.Key}",
                        path: Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Work), repository.Value.RepositoryPath),
                        deleteExisting: true);
                }
            }
            else if (string.Equals(workspace?.Clean, PipelineConstants.WorkspaceCleanOptions.Outputs, StringComparison.OrdinalIgnoreCase))
            {
                var allDirectories = Directory.GetDirectories(Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Work), trackingConfig.PipelineDirectory)).ToList();
                foreach (var repository in trackingConfig.Repositories)
                {
                    allDirectories.Remove(Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Work), repository.Value.RepositoryPath));
                }

                foreach (var deleteDir in allDirectories)
                {
                    executionContext.Debug($"Delete existing untracked directory '{deleteDir}'");
                    DeleteDirectory(executionContext, "untracked dir", deleteDir);
                }
            }
            else
            {
                CreateDirectory(
                    executionContext,
                    description: "pipeline directory",
                    path: Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Work), trackingConfig.PipelineDirectory),
                    deleteExisting: false);

                CreateDirectory(
                    executionContext,
                    description: "workspace directory",
                    path: Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Work), trackingConfig.WorkspaceDirectory),
                    deleteExisting: false);
            }

            return(trackingConfig);
        }