Clone(string parentPath, GitUrl url) { using (LogicalOperation.Start($"Cloning {url}")) { GitRepository.Clone(parentPath, url); } }
DistFiles(ProduceRepository repository, IEnumerable <string> sourceDirs) { Guard.NotNull(repository, nameof(repository)); Guard.NotNull(sourceDirs, nameof(sourceDirs)); var destDir = repository.GetWorkSubdirectory("distfiles"); if (Directory.Exists(destDir)) { using (LogicalOperation.Start("Deleting " + destDir)) Directory.Delete(destDir, true); } if (!sourceDirs.Where(p => Directory.Exists(p)).Any()) { return; } using (LogicalOperation.Start("Creating " + destDir)) Directory.CreateDirectory(destDir); foreach (var sourceDir in sourceDirs.Where(d => Directory.Exists(d))) { using (LogicalOperation.Start("Copying distributable files from " + sourceDir)) foreach (var sourceFile in Directory.EnumerateFiles(sourceDir, "*", SearchOption.AllDirectories)) { var localFile = sourceFile.Substring(sourceDir.Length + 1); var destFile = Path.Combine(destDir, localFile); Trace.TraceInformation(destFile); File.Copy(sourceFile, destFile); } } }
CheckOut(NuGitRepository repository, GitCommitName commit) { using (LogicalOperation.Start($"Checking out {commit}")) { repository.Checkout(commit); } }
Restore(NuGitRepository repository, bool exact) { var workspace = repository.Workspace; var lockDependencies = repository.ReadDotNuGitLock(); foreach (var d in lockDependencies) { using (LogicalOperation.Start($"Restoring {d.Url.RepositoryName} to {d.CommitName} ({d.CommitId})")) { var name = d.Url.RepositoryName; var r = workspace.FindRepository(name); if (r == null) { Clone(workspace.RootPath, d.Url); r = workspace.GetRepository(name); } var head = r.GetCommitId(new GitCommitName("HEAD")); var isCheckedOutToExact = head == d.CommitId; var isCheckedOutToDescendent = r.IsAncestor(d.CommitId, head); var hasUncommittedChanges = r.HasUncommittedChanges(); var isCommitNameAtCommitId = r.GetCommitId(d.CommitName) == d.CommitId; if (!exact && isCheckedOutToExact && hasUncommittedChanges) { Trace.TraceInformation($"Already checked out with uncommitted changes"); } else if (!exact && isCheckedOutToExact) { Trace.TraceInformation($"Already checked out"); } else if (!exact && isCheckedOutToDescendent && hasUncommittedChanges) { Trace.TraceInformation($"Already checked out to descendent with uncommitted changes"); } else if (!exact && isCheckedOutToDescendent) { Trace.TraceInformation($"Already checked out to descendent"); } else if (r.HasUncommittedChanges()) { Trace.TraceError("Uncommitted changes"); throw new UserException($"Uncommitted changes in {name}"); } else if (isCheckedOutToExact) { Trace.TraceInformation($"Already checked out"); } else if (isCommitNameAtCommitId) { CheckOut(r, d.CommitName); } else { CheckOut(r, d.CommitId); } } } }
GenerateProgramWrappers(ProduceWorkspace workspace) { Guard.NotNull(workspace, nameof(workspace)); var scripts = new HashSet <string>( workspace.FindRepositories() .Select(r => r.DotProducePath) .Where(p => File.Exists(p)) .Select(p => new DotProduce(p)) .Where(dp => dp != null) .SelectMany(dp => dp.Programs) .Select(path => Path.GetFileNameWithoutExtension(path)), StringComparer.OrdinalIgnoreCase); var orphans = Directory.GetFiles(workspace.GetBinDirectory()) .Where(file => !scripts.Contains(Path.GetFileNameWithoutExtension(file))) .ToList(); if (orphans.Count > 0) { using (LogicalOperation.Start("Deleting orphan program wrapper scripts")) { foreach (var file in orphans) { Trace.WriteLine(file); File.Delete(file); } } } }
Build( ProduceRepository repository, VisualStudioSolution sln, IList <VisualStudioSolutionProjectReference> projs, string framework) { var properties = new Dictionary <string, String>() { { "TargetFramework", framework }, }; var targets = projs.Select(p => $"{p.MSBuildTargetName}:Publish"); using (LogicalOperation.Start($"Building .NET for {framework}")) { var isNetFramework = Regex.IsMatch(framework, @"^net\d+$"); if (isNetFramework && !CanBuildNetFramework) { Trace.TraceInformation("This system can't build for .NET Framework"); return; } if (isNetFramework && BuildNetFrameworkUsingMSBuild) { MSBuild(repository, sln, properties, targets); return; } DotnetMSBuild(repository, sln, properties, targets); } }
protected override bool OnApply() { if (csprojs.Count > 1) { var incorrectCsprojs = csprojs .Where(csproj => csproj != correctCsprojName) .ToList(); foreach (var csproj in incorrectCsprojs) { using (LogicalOperation.Start($"Deleting {csproj}")) { var path = Path.Combine(Context.Path, csproj); File.Delete(path); csprojs.Remove(csproj); } } } if (csprojs.Count == 0) { using (LogicalOperation.Start($"Creating {correctCsprojName}")) { VisualStudioProject.Create(correctCsprojPath); } } return(true); }
Update(ProduceRepository repository) { using (LogicalOperation.Start("Updating NuGit dependencies")) if (ProcessExtensions.ExecuteAny(true, true, repository.Path, "nugit", "update") != 0) { throw new UserException("nugit failed"); } }
void RemoveBom(string path) { using (LogicalOperation.Start($"Removing UTF-8 BOM(s) from {path}")) { while (FileExtensions.DetectUtf8Bom(path) == true) { FileExtensions.RemoveFirst(path, FileExtensions.Utf8Bom.Count); } } }
Clean(ProduceRepository repository) { Guard.NotNull(repository, nameof(repository)); var workDir = repository.WorkDirectory; if (Directory.Exists(workDir)) { using (LogicalOperation.Start("Deleting " + workDir)) Directory.Delete(workDir, true); } }
protected override bool OnApply() { using (LogicalOperation.Start($"Renaming {slnName} to {correctSlnName}")) { var slnPath = Path.Combine(Context.Path, slnName); var correctSlnPath = Path.Combine(Context.Path, correctSlnName); File.Move(slnPath, correctSlnPath); } return(true); }
Restore(ProduceRepository repository, string slnPath) { if (slnPath == null) { return; } var sln = new VisualStudioSolution(slnPath); using (LogicalOperation.Start("Restoring NuGet packages")) Dotnet(repository, "restore", sln); }
protected override bool OnApply() { foreach (var file in filesWithIncorrectLineEndings) { using (LogicalOperation.Start($"Applying {lineEndingDescription} line endings to {file}")) { var lines = File.ReadAllLines(file); FileExtensions.WriteAllLines(file, lines, lineEnding, false); } } return(true); }
NugetPush(ProduceRepository repository, string nupkgPath) { Guard.NotNull(repository, nameof(repository)); if (nupkgPath == null) { return; } using (LogicalOperation.Start("Publishing nupkg")) { Dotnet(repository, "nuget", "push", nupkgPath, "-s", "https://api.nuget.org/v3/index.json"); } }
public void Pushes_And_Pops_Correctly() { int initialCount = Trace.CorrelationManager.LogicalOperationStack.Count; string op = "op"; using (LogicalOperation.Start(op)) { Trace.CorrelationManager.LogicalOperationStack.Count.ShouldBe(initialCount + 1); Trace.CorrelationManager.LogicalOperationStack.Peek().ShouldBe(op); } Trace.CorrelationManager.LogicalOperationStack.Count.ShouldBe(initialCount); }
GetProduceDirectory() { var path = IOPath.Combine(Path, ProduceDirectoryName); if (!Directory.Exists(path)) { using (LogicalOperation.Start("Creating " + path)) { Directory.CreateDirectory(path); } } return(path); }
Clean(ProduceRepository repository, string slnPath) { if (slnPath == null) { return; } var sln = new VisualStudioSolution(slnPath); var projs = FindLocalBuildableProjects(repository, sln); var targets = projs.Select(p => $"{p.MSBuildTargetName}:Clean"); using (LogicalOperation.Start("Cleaning .NET artifacts")) DotnetMSBuild(repository, sln, targets); }
GenerateProgramWrappers(ProduceRepository repository, IEnumerable <string> programs) { Guard.NotNull(programs, nameof(programs)); if (!programs.Any()) { return; } using (LogicalOperation.Start("Writing " + repository.Name + " program wrapper script(s)")) { var programDirectory = repository.Workspace.GetBinDirectory(); foreach (var program in programs) { var programBase = Path.GetFileNameWithoutExtension(program); var target = Path.Combine("..", "..", repository.Name, program); var cmdPath = Path.Combine(programDirectory, programBase) + ".cmd"; var shPath = Path.Combine(programDirectory, programBase); var cmd = GenerateCmd(target); var sh = GenerateSh(target); Trace.WriteLine(cmdPath); if (File.Exists(cmdPath)) { File.Move(cmdPath, cmdPath); // In case only the casing has changed } File.WriteAllText(cmdPath, cmd); Trace.WriteLine(shPath); if (File.Exists(shPath)) { File.Move(shPath, shPath); // In case only the casing has changed } File.WriteAllText(shPath, sh); if (!EnvironmentExtensions.IsWindows) { Process.Start("chmod", "u+x \"" + shPath + "\"").WaitForExit(); } } } }
RunCommand(ProduceRepository repository, string command) { using (LogicalOperation.Start(Invariant($"Running {command} command for {repository.Name}"))) { var graph = new Graph(repository.Workspace); foreach (var module in Modules) { module.Attach(repository, graph); } var target = graph.FindCommand(command); if (target == null) { Trace.TraceInformation(Invariant($"No {command} command")); return; } new Builder(graph).Build(target); } }
protected override bool OnApply() { if (slnNames.Count > 1) { var incorrectSlns = slnNames .Where(sln => sln != correctSlnName) .ToList(); foreach (var sln in incorrectSlns) { using (LogicalOperation.Start($"Deleting {sln}")) { var path = Path.Combine(Context.Path, sln); File.Delete(path); slnNames.Remove(sln); } } } if (slnNames.Count == 0) { using (LogicalOperation.Start($"Creating {correctSlnName}")) { var exitCode = ProcessExtensions.ExecuteAny( true, true, Context.Path, "dotnet", "new", "sln", "--name", correctSlnName); if (exitCode != 0) { Trace.TraceError("dotnet new sln failed"); return(false); } } } return(true); }
Pack(ProduceRepository repository, string slnPath, string projPath, string nupkgDir) { if (slnPath == null) { return; } if (projPath == null) { return; } Guard.Required(nupkgDir, nameof(nupkgDir)); if (!Path.IsPathRooted(nupkgDir)) { throw new ArgumentException("nupkgDir must be an absolute path", nameof(nupkgDir)); } var sln = new VisualStudioSolution(slnPath); var proj = sln.ProjectReferences.Single(p => p.AbsoluteLocation == projPath); var properties = new Dictionary <string, string>() { { "PackageOutputPath", nupkgDir }, }; var targets = new[] { $"{proj.MSBuildTargetName}:Pack" }; using (LogicalOperation.Start("Building nupkg")) { if (Directory.Exists(nupkgDir)) { Directory.Delete(nupkgDir, true); } Directory.CreateDirectory(nupkgDir); DotnetMSBuild(repository, sln, properties, targets); } }
protected override IDisposable OnApplying() { return(LogicalOperation.Start($"Applying {Description} in {Context.Name}/")); }
protected override IDisposable OnAnalysing() { return(LogicalOperation.Start($"Checking for {Description} in {Context.Name}/")); }
Install( NuGitRepository repository, VisualStudioSolution sln, GitRepositoryName dependencyName, string folderName, string folderId ) { var workspace = repository.Workspace; var slnLocalPath = PathExtensions.GetPathFromAncestor(sln.Path, repository.Path); var slnLocalPathComponents = PathExtensions.Split(slnLocalPath); var slnToWorkspacePath = Path.Combine(Enumerable.Repeat("..", slnLocalPathComponents.Length).ToArray()); var dependencyRepository = workspace.GetRepository(dependencyName); var dependencySln = dependencyRepository.FindVisualStudioSolution(); if (dependencySln == null) { return; } var dependencyProjects = FindDependencyProjects(dependencyRepository, dependencySln); if (dependencyProjects.Count == 0) { return; } using (LogicalOperation.Start($"Installing projects from {dependencyName}")) { // TODO Consider configurations in each individual dependency project, not just the solution var configurationsInCommon = sln.SolutionConfigurations.Intersect(dependencySln.SolutionConfigurations) .OrderBy(s => s) .ToList(); var folder = folderId != null ? sln.AddSolutionFolder(folderName, folderId) : sln.AddSolutionFolder(folderName); foreach (var project in dependencyProjects) { using (LogicalOperation.Start($"Installing {project.Name}")) { var projectLocalPath = PathExtensions.GetPathFromAncestor(project.AbsoluteLocation, dependencyRepository.Path); // // Add reference to the dependency project // sln.AddProjectReference( project.TypeId, project.Name, Path.Combine(slnToWorkspacePath, dependencyName, projectLocalPath), project.Id); // // Put it in the dependency's solution folder // sln.AddNestedProject(project.Id, folder.Id); // // Add solution -> project configuration mappings // foreach (string configuration in configurationsInCommon) { sln.AddProjectConfiguration(project.Id, configuration, "ActiveCfg", configuration); sln.AddProjectConfiguration(project.Id, configuration, "Build.0", configuration); } } } } }
Traverse( NuGitWorkspace workspace, IEnumerable <Dependency> dependencies, NuGitRepository requiredBy, IDictionary <GitRepositoryName, GitCommitName> checkedOut, ISet <GitRepositoryName> visited, Action <Dependency, NuGitRepository> onVisited ) { Guard.NotNull(workspace, nameof(workspace)); Guard.NotNull(dependencies, nameof(dependencies)); Guard.NotNull(checkedOut, nameof(checkedOut)); Guard.NotNull(visited, nameof(visited)); Guard.NotNull(onVisited, nameof(onVisited)); var unvisited = dependencies.Where(d => !visited.Contains(d.Url.RepositoryName)).ToList().AsReadOnly(); // // Clone any dependency repos that aren't present // foreach (var d in unvisited) { if (workspace.FindRepository(d.Url.RepositoryName) != null) { continue; } Clone(workspace.RootPath, d.Url); } // // Visit each dependency // foreach (var d in dependencies) { var name = d.Url.RepositoryName; var repo = workspace.GetRepository(name); var commit = d.CommitName; checkedOut.TryGetValue(name, out var checkedOutCommit); // // First visit wins // if (checkedOutCommit == null) { using (LogicalOperation.Start($"Restoring {d.Url.RepositoryName} to {d.CommitName}")) { var commitId = repo.GetCommitId(commit); var headId = repo.GetCommitId(); var isCheckedOutToCommit = headId == commitId; var hasUncommittedChanges = repo.HasUncommittedChanges(); if (repo.HasUncommittedChanges()) { Trace.TraceError("Uncommitted changes"); throw new UserException($"Uncommitted changes in {name}"); } else if (isCheckedOutToCommit) { Trace.TraceInformation($"Already checked out"); } else { CheckOut(repo, commit); } checkedOut.Add(name, commit); visited.Add(name); onVisited(d, repo); continue; } } // // Subsequent visits specifying different commits get a warning // if (commit != checkedOutCommit) { Trace.TraceWarning( StringExtensions.FormatInvariant( "{0} depends on {1}#{2} but #{3} has already been checked out", requiredBy.Name, name, commit, checkedOutCommit)); continue; } // // Subsequent visits specifying the same commit do nothing // } // // Recurse // foreach (var d in unvisited) { var name = d.Url.RepositoryName; var repo = workspace.FindRepository(name); Traverse( workspace, repo.ReadDotNuGit().Dependencies, repo, checkedOut, visited, onVisited); } }
protected virtual IDisposable OnApplying() { return(LogicalOperation.Start($"Applying {Description}")); }
protected virtual IDisposable OnAnalysing() { return(LogicalOperation.Start($"Checking for {Description}")); }