public override string GetLocalPath(IExecutionContext executionContext, RepositoryResource repository, string path)
        {
            ArgUtil.NotNull(executionContext, nameof(executionContext));
            ArgUtil.NotNull(executionContext.Variables, nameof(executionContext.Variables));
            ArgUtil.NotNull(repository, nameof(repository));
            ArgUtil.NotNull(repository.Endpoint, nameof(repository.Endpoint));

            path = path ?? string.Empty;
            if (path.StartsWith("$/") || path.StartsWith(@"$\"))
            {
                // Create the tf command manager.
                var tf = HostContext.CreateService <ITfsVCCommandManager>();
                tf.CancellationToken = CancellationToken.None;
                tf.Repository        = repository;
                tf.Endpoint          = executionContext.Endpoints.Single(x => (repository.Endpoint.Id != Guid.Empty && x.Id == repository.Endpoint.Id) || (repository.Endpoint.Id == Guid.Empty && string.Equals(x.Name, repository.Endpoint.Name, StringComparison.OrdinalIgnoreCase)));
                tf.ExecutionContext  = executionContext;

                // Attempt to resolve the path.
                string localPath = tf.ResolvePath(serverPath: path);
                if (!string.IsNullOrEmpty(localPath))
                {
                    return(localPath);
                }
            }

            // Return the original path.
            return(path);
        }
Exemple #2
0
        public override string GetLocalPath(IExecutionContext executionContext, RepositoryResource repository, string path)
        {
            Trace.Verbose("Entering SvnSourceProvider.GetLocalPath");

            ISvnCommandManager svn = HostContext.CreateService <ISvnCommandManager>();

            svn.Init(executionContext, repository, CancellationToken.None);

            // We assume that this is a server path first.
            string serverPath = svn.NormalizeRelativePath(path, '/', '\\').Trim();
            string localPath;

            if (serverPath.StartsWith("^/"))
            {
                // Convert the server path to the relative one using SVN work copy mappings
                string sourcesDirectory = repository.Properties.Get <string>(RepositoryPropertyNames.Path);
                localPath = svn.ResolveServerPath(serverPath, sourcesDirectory);
            }
            else
            {
                // normalize the path back to the local file system one.
                localPath = svn.NormalizeRelativePath(serverPath, Path.DirectorySeparatorChar, '/');
            }

            Trace.Verbose("Leaving SvnSourceProvider.GetLocalPath");
            return(localPath);
        }
        private string GetDefaultRepositoryPath(
            IExecutionContext executionContext,
            RepositoryResource repository,
            TrackingConfig newConfig
            )
        {
            string repoPath      = String.Empty;
            string workDirectory = HostContext.GetDirectory(WellKnownDirectory.Work);

            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(workDirectory, repoSourceDirectory);
                }
                else
                {
                    repoPath = Path.Combine(workDirectory, newConfig.SourcesDirectory, RepositoryUtil.GetCloneDirectory(repository));
                }
            }
            else
            {
                // For single checkouts, the repository is rooted to the sources folder (_work/1/s)
                repoPath = Path.Combine(workDirectory, newConfig.SourcesDirectory);
            }

            return(repoPath);
        }
Exemple #4
0
        public static string GetSourceDirectoryHashKey(this RepositoryResource repository, IExecutionContext executionContext)
        {
            // Validate parameters.
            ArgUtil.NotNull(executionContext, nameof(executionContext));
            ArgUtil.NotNull(executionContext.Variables, nameof(executionContext.Variables));
            ArgUtil.NotNull(repository.Url, nameof(repository.Url));

            // Calculate the hash key.
            const string Format    = "{{{{ \r\n    \"system\" : \"build\", \r\n    \"collectionId\" = \"{0}\", \r\n    \"definitionId\" = \"{1}\", \r\n    \"repositoryUrl\" = \"{2}\", \r\n    \"sourceFolder\" = \"{{0}}\",\r\n    \"hashKey\" = \"{{1}}\"\r\n}}}}";
            string       hashInput = string.Format(
                CultureInfo.InvariantCulture,
                Format,
                executionContext.Variables.System_CollectionId,
                executionContext.Variables.System_DefinitionId,
                repository.Url.AbsoluteUri);

            using (SHA1 sha1Hash = SHA1.Create())
            {
                byte[]        data      = sha1Hash.ComputeHash(Encoding.UTF8.GetBytes(hashInput));
                StringBuilder hexString = new StringBuilder();
                for (int i = 0; i < data.Length; i++)
                {
                    hexString.Append(data[i].ToString("x2"));
                }

                return(hexString.ToString());
            }
        }
        public void TrackingConfig_ctor_should_fill_in_fields_correctly()
        {
            using (TestHostContext tc = Setup(out Mock <IExecutionContext> mockExecutionContext))
            {
                // Arrange.
                var repository = new RepositoryResource()
                {
                    Type = RepositoryTypes.Git, Url = new Uri(RepositoryUrl)
                };

                // Act.
                var config = new TrackingConfig(mockExecutionContext.Object, new[] { repository }, DefinitionId);

                // Assert.
                Assert.Equal(Path.Combine("322", "a"), config.ArtifactsDirectory);
                Assert.Equal("322", config.BuildDirectory);
                Assert.Equal(CollectionId, config.CollectionId);
                Assert.Equal(CollectionUrl, config.CollectionUrl);
                Assert.Equal(DefinitionId.ToString(), config.DefinitionId);
                Assert.Equal(DefinitionName, config.DefinitionName);
                Assert.Equal(3, config.FileFormatVersion);
                Assert.Equal(null, config.FileLocation);
                Assert.Equal("ea7c71421cca06c927f73627b66d6b4f4c3a5f4a", config.HashKey);
                Assert.Equal(RepositoryTypes.Git, config.RepositoryType);
                Assert.Equal(RepositoryUrl, config.RepositoryUrl);
                Assert.Equal(Path.Combine("322", "s"), config.SourcesDirectory);
                Assert.Equal("build", config.System);
                Assert.Equal(Path.Combine("322", "TestResults"), config.TestResultsDirectory);
                Assert.NotNull(config.RepositoryTrackingInfo);
                Assert.Equal(true, config.ShouldSerializeRepositoryTrackingInfo());
                Assert.Equal(1, config.RepositoryTrackingInfo.Count);
                Assert.Equal(RepositoryUrl, config.RepositoryTrackingInfo[0].RepositoryUrl);
            }
        }
Exemple #6
0
        public void GetRepository_should_return_correct_value_when_called()
        {
            using (TestHostContext hc = new TestHostContext(this))
            {
                Tracing trace = hc.GetTrace();

                var repo1 = new RepositoryResource
                {
                    Alias = "repo1",
                    Id    = "repo1",
                    Type  = "git",
                };

                var repo2 = new RepositoryResource
                {
                    Alias = "repo2",
                    Id    = "repo2",
                    Type  = "git",
                };

                var repoSelf = new RepositoryResource
                {
                    Alias = "self",
                    Id    = "repo3",
                    Type  = "git",
                };

                Assert.Equal(repo1, RepositoryUtil.GetRepository(new[] { repo1, repo2 }, "repo1"));
                Assert.Equal(repo2, RepositoryUtil.GetRepository(new[] { repo1, repo2 }, "repo2"));
                Assert.Equal(repo1, RepositoryUtil.GetRepository(new[] { repoSelf, repo1, repo2 }, "repo1"));
                Assert.Equal(repo2, RepositoryUtil.GetRepository(new[] { repoSelf, repo1, repo2 }, "repo2"));
                Assert.Equal(repoSelf, RepositoryUtil.GetRepository(new[] { repoSelf, repo1, repo2 }, "self"));
                Assert.Equal(null, RepositoryUtil.GetRepository(new[] { repoSelf, repo1, repo2 }, "unknown"));
            }
        }
Exemple #7
0
        public void GetCloneDirectory_REPO_should_return_proper_value_when_called()
        {
            using (TestHostContext hc = new TestHostContext(this))
            {
                Tracing trace = hc.GetTrace();

                var repo = new RepositoryResource()
                {
                    Alias = "alias",
                    Id    = "repo1",
                    Type  = "git",
                    Url   = null,
                };

                // If name is not set and url is not set, then it should use alias
                Assert.Equal("alias", RepositoryUtil.GetCloneDirectory(repo));

                // If url is set, it should choose url over alias
                repo.Url = new Uri("https://[email protected]/jpricket/MyFirstProject/_git/repo1_url");
                Assert.Equal("repo1_url", RepositoryUtil.GetCloneDirectory(repo));

                // If name is set, it should choose name over alias or url
                repo.Properties.Set(RepositoryPropertyNames.Name, "MyFirstProject/repo1_name");
                Assert.Equal("repo1_name", RepositoryUtil.GetCloneDirectory(repo));
            }
        }
        public TrackingConfig UpdateDirectory(
            IExecutionContext executionContext,
            RepositoryResource repository)
        {
            // Validate parameters.
            Trace.Entering();
            ArgUtil.NotNull(executionContext, nameof(executionContext));
            ArgUtil.NotNull(executionContext.Variables, nameof(executionContext.Variables));
            ArgUtil.NotNull(repository, nameof(repository));
            var trackingManager = HostContext.GetService <ITrackingManager>();

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

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

            // Load the existing tracking file.
            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);

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

            TrackingConfig newConfig = ConvertToNewFormat(executionContext, repository, existingConfig);

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

            var repoPath = repository.Properties.Get <string>(RepositoryPropertyNames.Path);

            ArgUtil.NotNullOrEmpty(repoPath, nameof(repoPath));
            Trace.Info($"Update repository path for repository {repository.Alias} to '{repoPath}'");

            string buildDirectory = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Work), newConfig.BuildDirectory);

            if (repoPath.StartsWith(buildDirectory + Path.DirectorySeparatorChar) || repoPath.StartsWith(buildDirectory + Path.AltDirectorySeparatorChar))
            {
                // The sourcesDirectory in tracking file is a relative path to agent's work folder.
                newConfig.SourcesDirectory = repoPath.Substring(HostContext.GetDirectory(WellKnownDirectory.Work).Length + 1).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
            }
            else
            {
                throw new ArgumentException($"Repository path '{repoPath}' should be located under agent's work directory '{buildDirectory}'.");
            }

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

            return(newConfig);
        }
Exemple #9
0
 public RepositoryTrackingInfo(RepositoryResource repositoryResource, string sourcesDirectoryRoot)
 {
     if (repositoryResource != null)
     {
         Identifier       = repositoryResource.Alias;
         RepositoryType   = repositoryResource.Type;
         RepositoryUrl    = repositoryResource.Url.AbsoluteUri;
         SourcesDirectory = Path.Combine(sourcesDirectoryRoot, RepositoryUtil.GetCloneDirectory(repositoryResource));
     }
 }
Exemple #10
0
        private TrackingConfig ConvertToNewFormat(
            IExecutionContext executionContext,
            RepositoryResource repository,
            TrackingConfigBase config)
        {
            Trace.Entering();

            // If it's already in the new format, return it.
            TrackingConfig newConfig = config as TrackingConfig;

            if (newConfig != null)
            {
                return(newConfig);
            }

            // Delete the legacy artifact/staging directories.
            LegacyTrackingConfig legacyConfig = config as LegacyTrackingConfig;

            DeleteDirectory(
                executionContext,
                description: "legacy artifacts directory",
                path: Path.Combine(legacyConfig.BuildDirectory, Constants.Build.Path.LegacyArtifactsDirectory));
            DeleteDirectory(
                executionContext,
                description: "legacy staging directory",
                path: Path.Combine(legacyConfig.BuildDirectory, Constants.Build.Path.LegacyStagingDirectory));

            // Determine the source directory name. Check if the directory is named "s" already.
            // Convert the source directory to be named "s" if there is a problem with the old name.
            string sourcesDirectoryNameOnly = Constants.Build.Path.SourcesDirectory;
            string repositoryName           = repository.Properties.Get <string>(RepositoryPropertyNames.Name);

            if (!Directory.Exists(Path.Combine(legacyConfig.BuildDirectory, sourcesDirectoryNameOnly)) &&
                !String.Equals(repositoryName, Constants.Build.Path.ArtifactsDirectory, StringComparison.OrdinalIgnoreCase) &&
                !String.Equals(repositoryName, Constants.Build.Path.LegacyArtifactsDirectory, StringComparison.OrdinalIgnoreCase) &&
                !String.Equals(repositoryName, Constants.Build.Path.LegacyStagingDirectory, StringComparison.OrdinalIgnoreCase) &&
                !String.Equals(repositoryName, Constants.Build.Path.TestResultsDirectory, StringComparison.OrdinalIgnoreCase) &&
                !repositoryName.Contains("\\") &&
                !repositoryName.Contains("/") &&
                Directory.Exists(Path.Combine(legacyConfig.BuildDirectory, repositoryName)))
            {
                sourcesDirectoryNameOnly = repositoryName;
            }

            // Convert to the new format.
            newConfig = new TrackingConfig(
                executionContext,
                legacyConfig,
                sourcesDirectoryNameOnly,
                repository.Type,
                // The legacy artifacts directory has been deleted at this point - see above - so
                // switch the configuration to using the new naming scheme.
                useNewArtifactsDirectoryName: true);
            return(newConfig);
        }
        /// <summary>
        /// Returns the folder name that would be created by calling 'git.exe clone'.
        /// This is just the relative folder name not a full path.
        /// The repo name is used if provided, then repo url, and finally repo alias.
        /// </summary>
        public static string GetCloneDirectory(RepositoryResource repository)
        {
            ArgUtil.NotNull(repository, nameof(repository));

            string repoName =
                repository.Properties.Get <string>(RepositoryPropertyNames.Name) ??
                repository.Url?.AbsoluteUri ??
                repository.Alias;

            return(GetCloneDirectory(repoName));
        }
Exemple #12
0
 public static Boolean TestOverrideBuildDirectory(this RepositoryResource repository, AgentSettings settings)
 {
     if (repository.Type == TeamFoundation.DistributedTask.Pipelines.RepositoryTypes.Tfvc)
     {
         return(settings.IsHosted);
     }
     else
     {
         return(false);
     }
 }
        public void GetRepositoryForLocalPath_should_return_correct_values()
        {
            using (TestHostContext hc = new TestHostContext(this))
            {
                Tracing trace = hc.GetTrace();

                var repo1 = new RepositoryResource
                {
                    Alias = "repo1",
                    Id    = "repo1",
                    Type  = "git",
                };
                repo1.Properties.Set(RepositoryPropertyNames.Path, Path.Combine("root", "1", "s", "repo1"));

                var repo2 = new RepositoryResource
                {
                    Alias = "repo2",
                    Id    = "repo2",
                    Type  = "git",
                };
                repo2.Properties.Set(RepositoryPropertyNames.Path, Path.Combine("root", "1", "s", "repo2"));

                var repo3 = new RepositoryResource
                {
                    Alias = "repo3",
                    Id    = "repo3",
                    Type  = "git",
                };
                // repo3 has no path

                // Make sure null is returned if nothing matches or inputs are invalid
                Assert.Equal(null, RepositoryUtil.GetRepositoryForLocalPath(null, null));
                Assert.Equal(null, RepositoryUtil.GetRepositoryForLocalPath(null, Path.Combine("root", "1", "s", "not_a_repo")));
                Assert.Equal(null, RepositoryUtil.GetRepositoryForLocalPath(new[] { repo1, repo2, repo3 }, null));
                Assert.Equal(null, RepositoryUtil.GetRepositoryForLocalPath(new[] { repo1, repo2, repo3 }, "not a path"));
                Assert.Equal(null, RepositoryUtil.GetRepositoryForLocalPath(new[] { repo1, repo2, repo3 }, Path.Combine("root", "1", "s", "not_a_repo")));
                Assert.Equal(null, RepositoryUtil.GetRepositoryForLocalPath(new[] { repo1, repo2, repo3 }, Path.Combine("root", "1", "s")));
                Assert.Equal(null, RepositoryUtil.GetRepositoryForLocalPath(new[] { repo1, repo2, repo3 }, Path.Combine("root", "1", "s", "repo3")));

                // Make sure the first repo is returned if there is only one
                Assert.Equal(repo1, RepositoryUtil.GetRepositoryForLocalPath(new[] { repo1 }, Path.Combine("root", "1", "s", "not_a_repo")));
                Assert.Equal(repo2, RepositoryUtil.GetRepositoryForLocalPath(new[] { repo2 }, "not a path"));
                Assert.Equal(repo3, RepositoryUtil.GetRepositoryForLocalPath(new[] { repo3 }, "not a path"));

                // Make sure the matching repo is returned if there is more than one
                Assert.Equal(repo1, RepositoryUtil.GetRepositoryForLocalPath(new[] { repo1, repo2, repo3 }, Path.Combine("root", "1", "s", "repo1")));
                Assert.Equal(repo1, RepositoryUtil.GetRepositoryForLocalPath(new[] { repo1, repo2, repo3 }, Path.Combine("root", "1", "s", "repo1", "sub", "path", "file.txt")));
                Assert.Equal(repo2, RepositoryUtil.GetRepositoryForLocalPath(new[] { repo1, repo2, repo3 }, Path.Combine("root", "1", "s", "repo2")));
                Assert.Equal(repo2, RepositoryUtil.GetRepositoryForLocalPath(new[] { repo1, repo2, repo3 }, Path.Combine("root", "1", "s", "repo2", "sub", "path", "file.txt")));
                Assert.Equal(repo2, RepositoryUtil.GetRepositoryForLocalPath(new[] { repo3, repo1, repo2 }, Path.Combine("root", "1", "s", "repo2")));
                Assert.Equal(repo2, RepositoryUtil.GetRepositoryForLocalPath(new[] { repo3, repo1, repo2 }, Path.Combine("root", "1", "s", "repo2", "sub", "path", "file.txt")));
            }
        }
Exemple #14
0
        private void InitializeExecutionContext(TestHostContext hc, bool isMultiCheckout = false)
        {
            List <string> warnings;

            _variables = new Variables(
                hostContext: hc,
                copy: new Dictionary <string, VariableValue>(),
                warnings: out warnings);
            _repositories = new List <RepositoryResource>();
            _selfRepo     = new RepositoryResource()
            {
                Alias = "self",
                Id    = Guid.NewGuid().ToString(),
                Name  = "mainRepo",
                Type  = "git",
            };
            _selfRepo.Properties.Set(RepositoryPropertyNames.Path, "/1/s");
            _otherRepo = new RepositoryResource()
            {
                Alias = "repo2",
                Id    = Guid.NewGuid().ToString(),
                Name  = "otherRepo",
                Type  = "git",
            };
            _otherRepo.Properties.Set(RepositoryPropertyNames.Path, "/1/otherRepo");
            _repositories.Add(_selfRepo);
            _repositories.Add(_otherRepo);

            _ec = new Mock <IExecutionContext>();
            _ec.SetupAllProperties();
            _ec.Setup(x => x.Variables).Returns(_variables);
            _ec.Setup(x => x.Repositories).Returns(_repositories);
            _ec.Setup(x => x.GetHostContext()).Returns(hc);
            _ec.Setup(x => x.SetVariable(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <bool>(), It.IsAny <bool>(), It.IsAny <bool>(), It.IsAny <bool>()))
            .Callback <string, string, bool, bool, bool, bool>((name, value, secret, b2, b3, readOnly) => _variables.Set(name, value, secret, readOnly));

            if (isMultiCheckout)
            {
                var jobSettings = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);
                jobSettings.Add(Agent.Sdk.WellKnownJobSettings.HasMultipleCheckouts, Boolean.TrueString);
                _ec.Setup(x => x.JobSettings).Returns(jobSettings);
            }

            var directoryManager = new Mock <Microsoft.VisualStudio.Services.Agent.Worker.Build.IBuildDirectoryManager>();

            directoryManager.Setup(x => x.GetRelativeRepositoryPath(It.IsAny <string>(), It.IsAny <string>()))
            .Returns <string, string>((bd, path) => GetLastPathPart(path));

            hc.SetSingleton(directoryManager.Object);
        }
Exemple #15
0
        public TrackingConfig UpdateDirectory(
            IExecutionContext executionContext,
            RepositoryResource repository)
        {
            // Validate parameters.
            Trace.Entering();
            ArgUtil.NotNull(executionContext, nameof(executionContext));
            ArgUtil.NotNull(executionContext.Variables, nameof(executionContext.Variables));
            ArgUtil.NotNull(repository, nameof(repository));
            var trackingManager = HostContext.GetService <ITrackingManager>();

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

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

            // Load the existing tracking file.
            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);

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

            TrackingConfig newConfig = ConvertToNewFormat(executionContext, repository, existingConfig);

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

            var repoPath = repository.Properties.Get <string>(RepositoryPropertyNames.Path);

            ArgUtil.NotNullOrEmpty(repoPath, nameof(repoPath));
            Trace.Info($"Update repository path for repository {repository.Alias} to '{repoPath}'");

            string buildDirectory = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Work), newConfig.BuildDirectory);

            newConfig.SourcesDirectory = GetRelativeRepositoryPath(buildDirectory, repoPath);

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

            return(newConfig);
        }
Exemple #16
0
        public void Init(
            IExecutionContext context,
            RepositoryResource repository,
            CancellationToken cancellationToken)
        {
            // Validation.
            ArgUtil.NotNull(context, nameof(context));
            ArgUtil.NotNull(repository, nameof(repository));
            ArgUtil.NotNull(cancellationToken, nameof(cancellationToken));

            ArgUtil.NotNull(repository.Url, nameof(repository.Url));
            ArgUtil.Equal(true, repository.Url.IsAbsoluteUri, nameof(repository.Url.IsAbsoluteUri));

            ArgUtil.NotNull(repository.Endpoint, nameof(repository.Endpoint));
            ServiceEndpoint endpoint = context.Endpoints.Single(
                x => (repository.Endpoint.Id != Guid.Empty && x.Id == repository.Endpoint.Id) ||
                (repository.Endpoint.Id == Guid.Empty && string.Equals(x.Name, repository.Endpoint.Name.ToString(), StringComparison.OrdinalIgnoreCase)));

            ArgUtil.NotNull(endpoint.Data, nameof(endpoint.Data));
            ArgUtil.NotNull(endpoint.Authorization, nameof(endpoint.Authorization));
            ArgUtil.NotNull(endpoint.Authorization.Parameters, nameof(endpoint.Authorization.Parameters));
            ArgUtil.Equal(EndpointAuthorizationSchemes.UsernamePassword, endpoint.Authorization.Scheme, nameof(endpoint.Authorization.Scheme));

            _context           = context;
            _repository        = repository;
            _endpoint          = endpoint;
            _cancellationToken = cancellationToken;

            // Find svn in %Path%
            string svnPath = WhichUtil.Which("svn", trace: Trace);

            if (string.IsNullOrEmpty(svnPath))
            {
                throw new Exception(StringUtil.Loc("SvnNotInstalled"));
            }
            else
            {
                _context.Debug($"Found svn installation path: {svnPath}.");
                _svn = svnPath;
            }

            // External providers may need basic auth or tokens
            endpoint.Authorization.Parameters.TryGetValue(EndpointAuthorizationParameters.Username, out _username);
            endpoint.Authorization.Parameters.TryGetValue(EndpointAuthorizationParameters.Password, out _password);

            _acceptUntrusted = endpoint.Data.ContainsKey(EndpointData.SvnAcceptUntrustedCertificates) &&
                               StringUtil.ConvertToBoolean(endpoint.Data[EndpointData.SvnAcceptUntrustedCertificates], defaultValue: false);
        }
Exemple #17
0
 private string GetDefaultRepositoryPath(
     IExecutionContext executionContext,
     RepositoryResource repository,
     string defaultSourcesDirectory)
 {
     if (RepositoryUtil.HasMultipleCheckouts(executionContext.JobSettings))
     {
         // If we have multiple checkouts they should all be rooted to the sources directory (_work/1/s/repo1)
         return(Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Work), defaultSourcesDirectory, RepositoryUtil.GetCloneDirectory(repository)));
     }
     else
     {
         // For single checkouts, the repository is rooted to the sources folder (_work/1/s)
         return(Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Work), defaultSourcesDirectory));
     }
 }
        public void GetTriggeringRepository_should_return_correct_value_when_called()
        {
            using (TestHostContext hc = new TestHostContext(this))
            {
                Tracing trace = hc.GetTrace();

                var repo1 = new RepositoryResource
                {
                    Alias = "repo1",
                    Id    = "repo1",
                    Type  = "git",
                };

                var repo2 = new RepositoryResource
                {
                    Alias = "repo2",
                    Id    = "repo2",
                    Type  = "git",
                };

                var repoSelf = new RepositoryResource
                {
                    Alias = "self",
                    Id    = "repo3",
                    Type  = "git",
                };

                // No properties set
                Assert.Equal(null, RepositoryUtil.GetTriggeringRepository(null));
                Assert.Equal(repo1, RepositoryUtil.GetTriggeringRepository(new[] { repo1 }));
                Assert.Equal(repo2, RepositoryUtil.GetTriggeringRepository(new[] { repo2 }));
                Assert.Equal(repoSelf, RepositoryUtil.GetTriggeringRepository(new[] { repoSelf }));
                Assert.Equal(null, RepositoryUtil.GetTriggeringRepository(new[] { repo1, repo2 }));
                Assert.Equal(repoSelf, RepositoryUtil.GetTriggeringRepository(new[] { repoSelf, repo1, repo2 }));
                Assert.Equal(repoSelf, RepositoryUtil.GetTriggeringRepository(new[] { repo1, repoSelf, repo2 }));
                Assert.Equal(repoSelf, RepositoryUtil.GetTriggeringRepository(new[] { repo1, repo2, repoSelf }));

                // With IsPrimaryRepository set
                repo2.Properties.Set(RepositoryUtil.IsTriggeringRepository, Boolean.TrueString);
                Assert.Equal(repo2, RepositoryUtil.GetTriggeringRepository(new[] { repo1, repo2, repoSelf }));
                repo2.Properties.Set(RepositoryUtil.IsTriggeringRepository, Boolean.FalseString);
                Assert.Equal(repoSelf, RepositoryUtil.GetTriggeringRepository(new[] { repo1, repo2, repoSelf }));
            }
        }
        public TrackingConfig UpdateDirectory(
            IExecutionContext executionContext,
            RepositoryResource updatedRepository)
        {
            // Validate parameters.
            Trace.Entering();
            ArgUtil.NotNull(executionContext, nameof(executionContext));
            ArgUtil.NotNull(executionContext.Variables, nameof(executionContext.Variables));
            ArgUtil.NotNull(updatedRepository, nameof(updatedRepository));
            var trackingManager = HostContext.GetService <ITrackingManager>();

            // Determine new repository path
            var repoPath = updatedRepository.Properties.Get <string>(RepositoryPropertyNames.Path);

            ArgUtil.NotNullOrEmpty(repoPath, nameof(repoPath));
            Trace.Info($"Update repository path for repository {updatedRepository.Alias} to '{repoPath}'");

            // Get the config
            var trackingConfig = trackingManager.LoadExistingTrackingConfig(executionContext);

            // Update the repositoryInfo on the config
            string buildDirectory   = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Work), trackingConfig.BuildDirectory);
            string relativeRepoPath = GetRelativeRepositoryPath(buildDirectory, repoPath);
            var    effectedRepo     = trackingConfig.RepositoryTrackingInfo.FirstOrDefault(r => string.Equals(r.Identifier, updatedRepository.Alias, StringComparison.OrdinalIgnoreCase));

            if (effectedRepo != null)
            {
                Trace.Info($"Found repository {updatedRepository.Alias}'");
                effectedRepo.SourcesDirectory = relativeRepoPath;
            }

            // Also update the SourcesDirectory on the tracking info if there is only one repo.
            if (trackingConfig.RepositoryTrackingInfo.Count == 1)
            {
                Trace.Info($"Updating SourcesDirectory to {updatedRepository.Alias}'");
                trackingConfig.SourcesDirectory = relativeRepoPath;
            }

            // Update the tracking config files.
            Trace.Verbose("Updating job run properties.");
            trackingManager.UpdateTrackingConfig(executionContext, trackingConfig);

            return(trackingConfig);
        }
        public TrackingConfig(
            IExecutionContext executionContext,
            RepositoryResource repository,
            int buildDirectory,
            string hashKey)
        {
            // Set the directories.
            BuildDirectory       = buildDirectory.ToString(CultureInfo.InvariantCulture);
            ArtifactsDirectory   = Path.Combine(BuildDirectory, Constants.Build.Path.ArtifactsDirectory);
            SourcesDirectory     = Path.Combine(BuildDirectory, Constants.Build.Path.SourcesDirectory);
            TestResultsDirectory = Path.Combine(BuildDirectory, Constants.Build.Path.TestResultsDirectory);

            // Set the other properties.
            CollectionId   = executionContext.Variables.System_CollectionId;
            DefinitionId   = executionContext.Variables.System_DefinitionId;
            HashKey        = hashKey;
            RepositoryUrl  = repository.Url.AbsoluteUri;
            RepositoryType = repository.Type;
            System         = BuildSystem;
            UpdateJobRunProperties(executionContext);
        }
Exemple #21
0
 public Task <RepositoryResource> Update(RepositoryResource resource, string currentSlug = null)
 => ApiClientWrapper.Update <RepositoryResource>($"{RootUri}/{currentSlug ?? resource.Slug}", resource);
Exemple #22
0
 public Task Remove(RepositoryResource resource)
 => ApiClientWrapper.Remove($"{RootUri}/{resource.Slug}");
Exemple #23
0
        public TrackingConfig Create(
            IExecutionContext executionContext,
            RepositoryResource repository,
            string hashKey,
            string file,
            bool overrideBuildDirectory)
        {
            Trace.Entering();

            // Get or create the top-level tracking config.
            TopLevelTrackingConfig topLevelConfig;
            string topLevelFile = Path.Combine(
                HostContext.GetDirectory(WellKnownDirectory.Work),
                Constants.Build.Path.SourceRootMappingDirectory,
                Constants.Build.Path.TopLevelTrackingConfigFile);

            Trace.Verbose($"Loading top-level tracking config if exists: {topLevelFile}");
            if (!File.Exists(topLevelFile))
            {
                topLevelConfig = new TopLevelTrackingConfig();
            }
            else
            {
                topLevelConfig = JsonConvert.DeserializeObject <TopLevelTrackingConfig>(File.ReadAllText(topLevelFile));
                if (topLevelConfig == null)
                {
                    executionContext.Warning($"Rebuild corruptted top-level tracking configure file {topLevelFile}.");
                    // save the corruptted file in case we need to investigate more.
                    File.Copy(topLevelFile, $"{topLevelFile}.corruptted", true);

                    topLevelConfig = new TopLevelTrackingConfig();
                    DirectoryInfo workDir = new DirectoryInfo(HostContext.GetDirectory(WellKnownDirectory.Work));

                    foreach (var dir in workDir.EnumerateDirectories())
                    {
                        // we scan the entire _work directory and find the directory with the highest integer number.
                        if (int.TryParse(dir.Name, NumberStyles.Integer, CultureInfo.InvariantCulture, out int lastBuildNumber) &&
                            lastBuildNumber > topLevelConfig.LastBuildDirectoryNumber)
                        {
                            topLevelConfig.LastBuildDirectoryNumber = lastBuildNumber;
                        }
                    }
                }
            }

            // Determine the build directory.
            if (overrideBuildDirectory)
            {
                // This should only occur during hosted builds. This was added due to TFVC.
                // TFVC does not allow a local path for a single machine to be mapped in multiple
                // workspaces. The machine name for a hosted images is not unique.
                //
                // So if a customer is running two hosted builds at the same time, they could run
                // into the local mapping conflict.
                //
                // The workaround is to force the build directory to be different across all concurrent
                // hosted builds (for TFVC). The agent ID will be unique across all concurrent hosted
                // builds so that can safely be used as the build directory.
                ArgUtil.Equal(default(int), topLevelConfig.LastBuildDirectoryNumber, nameof(topLevelConfig.LastBuildDirectoryNumber));
                var           configurationStore = HostContext.GetService <IConfigurationStore>();
                AgentSettings settings           = configurationStore.GetSettings();
                topLevelConfig.LastBuildDirectoryNumber = settings.AgentId;
            }
            else
            {
                topLevelConfig.LastBuildDirectoryNumber++;
            }

            // Update the top-level tracking config.
            topLevelConfig.LastBuildDirectoryCreatedOn = DateTimeOffset.Now;
            WriteToFile(topLevelFile, topLevelConfig);

            // Create the new tracking config.
            TrackingConfig config = new TrackingConfig(
                executionContext,
                repository,
                topLevelConfig.LastBuildDirectoryNumber,
                hashKey);

            WriteToFile(file, config);
            return(config);
        }
Exemple #24
0
 public RepositoryScope ScopeToRepository(RepositoryResource repository)
 => new RepositoryScope(this, repository.Slug, _client);
        public TrackingConfig PrepareDirectory(
            IExecutionContext executionContext,
            RepositoryResource repository,
            WorkspaceOptions workspace)
        {
            // Validate parameters.
            Trace.Entering();
            ArgUtil.NotNull(executionContext, nameof(executionContext));
            ArgUtil.NotNull(executionContext.Variables, nameof(executionContext.Variables));
            ArgUtil.NotNull(repository, nameof(repository));
            var trackingManager = HostContext.GetService <ITrackingManager>();

            // Defer to the source provider to calculate the hash key.
            Trace.Verbose("Calculating build directory hash key.");
            string hashKey = repository.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,
                    repository,
                    hashKey,
                    trackingFile,
                    repository.TestOverrideBuildDirectory(agentSetting));
                ArgUtil.NotNull(newConfig, nameof(newConfig));
            }
            else
            {
                // Convert legacy format to the new format if required.
                newConfig = ConvertToNewFormat(executionContext, repository, 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 = repository.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.BuildDirectory, Constants.Build.Path.SourcesDirectory),
                deleteExisting: cleanOption == BuildCleanOption.Source);

            return(newConfig);
        }
Exemple #26
0
 public void Init()
 {
     sharpBucket          = TestHelpers.GetV2ClientAuthenticatedWithOAuth();
     repositoriesEndPoint = sharpBucket.RepositoriesEndPoint();
     repositoryResource   = repositoriesEndPoint.RepositoryResource(ACCOUNT_NAME, REPOSITORY_NAME);
 }
 public virtual string GetLocalPath(IExecutionContext executionContext, RepositoryResource repository, string path)
 {
     return(path);
 }
Exemple #28
0
        public static async Task <(bool success, string error)> InsertRepositoryEntity(RepositoryResource resource, CloudTable table, ILogger log)
        {
            log.LogInformation($"");

            try
            {
                var newEntity = new RepositoryEntity(resource.Owner, resource.Name);
                newEntity.Subscribers.Add(resource.Subscriber);
                var insertOperation = TableOperation.Insert(newEntity);
                await table.ExecuteAsync(insertOperation);
            }
            catch (StorageException sex)
            {
                return(false, sex.RequestInformation.ExtendedErrorInformation.ErrorMessage);
            }
            catch (Exception ex)
            {
                return(false, ex.Message);
            }

            return(true, "");
        }
        private ISourceProvider GetSourceProvider(IExecutionContext executionContext, RepositoryResource repository)
        {
            if (repository != null)
            {
                var extensionManager = HostContext.GetService <IExtensionManager>();
                List <ISourceProvider> sourceProviders = extensionManager.GetExtensions <ISourceProvider>();
                var sourceProvider = sourceProviders.FirstOrDefault(x => string.Equals(x.RepositoryType, repository.Type, StringComparison.OrdinalIgnoreCase));
                return(sourceProvider);
            }

            return(null);
        }
Exemple #30
0
        public static async Task <(bool success, string error)> UpdateRepositoryEntity(RepositoryEntity existing, RepositoryResource resource, CloudTable table, ILogger log)
        {
            if (!existing.Subscribers.Contains(resource.Subscriber))
            {
                log.LogInformation($"");

                try
                {
                    existing.Subscribers.Add(resource.Subscriber);
                    var updateOperation = TableOperation.Replace(existing);
                    await table.ExecuteAsync(updateOperation);
                }
                catch (StorageException sex)
                {
                    return(false, sex.RequestInformation.ExtendedErrorInformation.ErrorMessage);
                }
                catch (Exception ex)
                {
                    return(false, ex.Message);
                }
            }
            return(true, "");
        }