private async Task FindBaselineBranchAsync(MigrationContext context, MigratedProject project, CancellationToken cancellationToken) { Logger.Info($"Looking for releases branch for '{project.SourcePath}'"); //Look for the releases folder (string itemPath, Version version) = await context.SourceService.FindLatestVersionAsync(ItemPath.BuildPath(project.SourcePath, Settings.ReleaseBranch), cancellationToken).ConfigureAwait(false); //If there is a latest release then we'll use it as baseline otherwise download the baseline branch if (String.IsNullOrEmpty(itemPath)) { Logger.Debug($"No releases found, looking for base branch from '{project.SourcePath}'"); var baseline = await context.SourceService.FindItemAsync(ItemPath.BuildPath(project.SourcePath, Settings.BaselineBranch), false, cancellationToken).ConfigureAwait(false); if (baseline != null) { itemPath = baseline.Path; } ; } ; if (!String.IsNullOrEmpty(itemPath)) { project.BaselinePath = itemPath; project.Version = version; } ; Logger.Info($"Found branch for '{project.SourcePath}' - baseline Path = {itemPath}, Version = {version}"); }
private async Task CommitRepoAsync(MigratedProject project, GitCommand command, string message, CancellationToken cancellationToken) { Logger.Info($"Committing repo '{project.DestinationFullPath}' - {message}"); //Have to use Git for this await command.CommitAndPushChangesAsync(project.LocalFullPath, Settings.GitMasterBranch, message, cancellationToken).ConfigureAwait(false); }
private async Task CreateReleaseBranchAsync(MigratedProject project, GitCommand command, CancellationToken cancellationToken) { Logger.Info($"Creating branch for release for '{project.DestinationFullPath}"); var branchName = await BuildBranchNameAsync(project, Settings.GitReleaseBranch, cancellationToken).ConfigureAwait(false); Logger.Info($"Branch = {branchName}"); //Have to use Git for this await command.CheckOutBranchAsync(project.LocalFullPath, branchName, true, cancellationToken).ConfigureAwait(false); //Have to use Git for this //We have already pulled over the files so we can just commit to snapshot the release branch await command.CommitAndPushChangesAsync(project.LocalFullPath, branchName, $"Import of release {project.Version}", cancellationToken).ConfigureAwait(false); }
private Task <string> BuildBranchNameAsync(MigratedProject project, string branch, CancellationToken cancellationToken) { return(Task.Run(() => { var engine = new TextSubstitutionEngine("{", "}"); engine.Rules.Add(new SimpleTextSubstitutionRule("major", project.Version?.Major.ToString() ?? "0")); engine.Rules.Add(new SimpleTextSubstitutionRule("minor", project.Version?.Minor.ToString() ?? "0")); engine.Rules.Add(new SimpleTextSubstitutionRule("build", project.Version?.Build.ToString() ?? "0")); engine.Rules.Add(new SimpleTextSubstitutionRule("revision", project.Version?.Revision.ToString() ?? "0")); engine.Rules.Add(new SimpleTextSubstitutionRule("version", project.Version?.ToString() ?? "0.0.0.0")); engine.Rules.Add(new SimpleTextSubstitutionRule("yyyy", DateTime.Now.ToString("yyyy"))); engine.Rules.Add(new SimpleTextSubstitutionRule("MM", DateTime.Now.ToString("MM"))); engine.Rules.Add(new SimpleTextSubstitutionRule("dd", DateTime.Now.ToString("dd"))); engine.Rules.Add(new SimpleTextSubstitutionRule("MMM", DateTime.Now.ToString("MMM"))); engine.Rules.Add(new SimpleTextSubstitutionRule("yy", DateTime.Now.ToString("yy"))); return engine.Process(branch); }, cancellationToken)); }
private async Task UpdateMetadataFileAsync(string metadataFile, MigratedProject project, CancellationToken cancellationToken) { Logger.Info($"Updating metadata file '{metadataFile}'"); //Open or create the file if (!File.Exists(metadataFile)) { Logger.Warning($"No metadata file found '{metadataFile}"); return; } ; await Task.Run(() => { var engine = new TextSubstitutionEngine("{", "}"); engine.Rules.Add(new ObjectTextSubstitutionRule <MigratedProject>(project)); engine.Rules.Add(new SimpleTextSubstitutionRule("Date", DateTime.Now.ToString())); engine.Rules.Add(new SimpleTextSubstitutionRule("TfsCollectionUrl", Host.Settings.SourceCollectionUrl)); var text = File.ReadAllText(metadataFile); text = engine.Process(text); File.WriteAllText(metadataFile, text); }, cancellationToken).ConfigureAwait(false); }
private async Task <MigratedProject> MigrateProjectAsync(MigrationContext context, ProjectSettings projectToMigrate, CancellationToken cancellationToken) { Logger.StartActivity($"Migrating project '{projectToMigrate.SourcePath}'"); var migratedProject = new MigratedProject() { SourcePath = projectToMigrate.SourcePath, LocalFullPath = FileSystem.BuildPath(context.OutputPath, projectToMigrate.DestinationPath), DestinationPath = projectToMigrate.DestinationPath, DestinationProjectName = projectToMigrate.DestinationProject }; migratedProject.StartProfiling(); try { using (var logger = Logger.BeginScope("MigrateProject")) { // Create the target repo migratedProject.DestinationRepo = await CreateGitRepoAsync(context, migratedProject, cancellationToken).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); if (projectToMigrate.HasBranches) { // Find the baseline branch for this project, if any await FindBaselineBranchAsync(context, migratedProject, cancellationToken).ConfigureAwait(false); if (!String.IsNullOrEmpty(migratedProject.BaselinePath)) { cancellationToken.ThrowIfCancellationRequested(); // Download the baseline await DownloadFolderAsync(context.SourceService, migratedProject.BaselinePath, migratedProject.LocalFullPath, cancellationToken).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); // Clean the folder var fileCount = await CleanFolderAsync(migratedProject.LocalFullPath, cancellationToken).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); // It is possible that the baseline branch is actually empty in which case we'll // get an error when trying to commit so skip this if there are no files if (fileCount > 0) { // Commit the changes to the master branch var msg = $"Committing baseline version from TFS - {migratedProject.BaselinePath}"; await CommitRepoAsync(migratedProject, context.GitCommand, msg, cancellationToken).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); // Create a release for this version so it can be found later if there is a release if (migratedProject.Version != null) { await CreateReleaseBranchAsync(migratedProject, context.GitCommand, cancellationToken).ConfigureAwait(false); //Switch back to master because we won't be doing anything else with this branch Logger.Debug($"Changing to branch '{Settings.GitMasterBranch}'"); await context.GitCommand.CheckOutBranchAsync(migratedProject.LocalFullPath, Settings.GitMasterBranch, false, cancellationToken).ConfigureAwait(false); } ; } else { Logger.Warning($"No files in baseline '{migratedProject.BaselinePath}', skipping commit of master branch"); } cancellationToken.ThrowIfCancellationRequested(); } ; } ; // Download the latest version of the code to master { migratedProject.DevelopmentPath = projectToMigrate.HasBranches ? ItemPath.BuildPath(migratedProject.SourcePath, Settings.DevelopmentBranch) : migratedProject.SourcePath; // We need to be able to tell what stuff was deleted so wipe the directory structure and start over, except the .git folder await FileSystem.ClearDirectoryAsync(migratedProject.LocalFullPath, new[] { ".git" }, cancellationToken).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); // Download the dev branch await DownloadFolderAsync(context.SourceService, migratedProject.DevelopmentPath, migratedProject.LocalFullPath, cancellationToken).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); // Clean the folder await CleanFolderAsync(migratedProject.LocalFullPath, cancellationToken).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); // Copy the template files over any existing files await CopyTemplateAsync(migratedProject.LocalFullPath, Settings.TemplatePath, cancellationToken).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); // Update the metadata file, if any if (!String.IsNullOrEmpty(Settings.MetadataFile)) { var metadataFile = FileSystem.BuildPath(migratedProject.LocalFullPath, Settings.MetadataFile); await UpdateMetadataFileAsync(metadataFile, migratedProject, cancellationToken).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); } ; // Commit the changes var msg = $"Committing latest version from TFS - {migratedProject.DevelopmentPath}"; await CommitRepoAsync(migratedProject, context.GitCommand, msg, cancellationToken).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); }; //Clean up the structure if set if (Settings.CleanAfterCommit) { await FileSystem.RemoveDirectoryAsync(migratedProject.LocalFullPath, cancellationToken).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); } ; }; var totalTime = migratedProject.StopProfiling(); Logger.StopActivity($"Migrated project '{projectToMigrate.SourcePath}' in {totalTime}"); } catch (Exception e) { migratedProject.Error = e; Logger.Error(e); }; return(migratedProject); }
private async Task <GitRepository> CreateGitRepoAsync(MigrationContext context, MigratedProject project, CancellationToken cancellationToken) { var targetProject = await context.TargetServer.FindProjectAsync(project.DestinationProjectName, cancellationToken).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); var repo = new GitRepository() { ProjectReference = targetProject, Name = project.DestinationPath }; //Get the repo, if it exists var existingRepo = await context.TargetService.FindRepositoryAsync(targetProject, repo.Name, cancellationToken).ConfigureAwait(false); Logger.Debug($"Creating Git repo '{project.DestinationFullPath}'"); //Delete the repo if it exists if (existingRepo != null) { Logger.Debug($"Deleting repo '{project.DestinationFullPath}'"); await context.TargetService.DeleteRepositoryAsync(existingRepo, cancellationToken).ConfigureAwait(false); } ; //Clone the repo locally Logger.Debug($"Initializing repo '{project.DestinationFullPath}' to '{project.LocalFullPath}'"); return(await CreateLocalRepositoryAsync(context, repo, context.OutputPath, cancellationToken).ConfigureAwait(false)); }