mirror of https://github.com/abpframework/abp.git
committed by
GitHub
4 changed files with 251 additions and 0 deletions
@ -0,0 +1,125 @@ |
|||
using Microsoft.Extensions.Logging; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.IO; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Cli.Args; |
|||
using Volo.Abp.Cli.ProjectModification; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.Cli.Commands; |
|||
|
|||
public class SwitchToLocal : IConsoleCommand, ITransientDependency |
|||
{ |
|||
private readonly LocalReferenceConverter _localReferenceConverter; |
|||
public const string Name = "switch-to-local"; |
|||
|
|||
public ILogger<SwitchToLocal> Logger { get; set; } |
|||
|
|||
public SwitchToLocal(LocalReferenceConverter localReferenceConverter) |
|||
{ |
|||
_localReferenceConverter = localReferenceConverter; |
|||
} |
|||
|
|||
public async Task ExecuteAsync(CommandLineArgs commandLineArgs) |
|||
{ |
|||
var workingDirectory = GetWorkingDirectory(commandLineArgs) ?? Directory.GetCurrentDirectory(); |
|||
|
|||
if (!Directory.Exists(workingDirectory)) |
|||
{ |
|||
throw new CliUsageException( |
|||
"Specified directory does not exist." + |
|||
Environment.NewLine + Environment.NewLine + |
|||
GetUsageInfo() |
|||
); |
|||
} |
|||
|
|||
await _localReferenceConverter.ConvertAsync(workingDirectory, GetPaths(commandLineArgs)); |
|||
} |
|||
|
|||
private List<string> GetPaths(CommandLineArgs commandLineArgs) |
|||
{ |
|||
var paths = commandLineArgs.Options.GetOrNull( |
|||
Options.LocalPaths.Short, |
|||
Options.LocalPaths.Long |
|||
); |
|||
|
|||
if (paths == null) |
|||
{ |
|||
throw new CliUsageException( |
|||
"Local paths are not specified!" + |
|||
Environment.NewLine + Environment.NewLine + |
|||
GetUsageInfo() |
|||
); |
|||
} |
|||
|
|||
return paths.Split("|").Select(x=> x.Trim()).ToList(); |
|||
} |
|||
|
|||
private string GetWorkingDirectory(CommandLineArgs commandLineArgs) |
|||
{ |
|||
var path = commandLineArgs.Options.GetOrNull( |
|||
Options.SolutionPath.Short, |
|||
Options.SolutionPath.Long |
|||
); |
|||
|
|||
if (path == null) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
if (path.EndsWith(".sln") || path.EndsWith(".csproj")) |
|||
{ |
|||
return Path.GetDirectoryName(path); |
|||
} |
|||
|
|||
return path; |
|||
} |
|||
|
|||
public string GetShortDescription() |
|||
{ |
|||
return "Changes all NuGet package references to local project references for all the .csproj files in the specified folder" + |
|||
" (and all its subfolders with any deep)"; |
|||
} |
|||
|
|||
public string GetUsageInfo() |
|||
{ |
|||
var sb = new StringBuilder(); |
|||
|
|||
sb.AppendLine(""); |
|||
sb.AppendLine("Usage:"); |
|||
sb.AppendLine(""); |
|||
sb.AppendLine(" abp switch-to-local [options]"); |
|||
sb.AppendLine(""); |
|||
sb.AppendLine("Options:"); |
|||
sb.AppendLine(""); |
|||
sb.AppendLine("-s |--solution <directory-path> (default: current directory)"); |
|||
sb.AppendLine("-p | --paths <local-paths> (Required)"); |
|||
sb.AppendLine(""); |
|||
sb.AppendLine("Examples:"); |
|||
sb.AppendLine(""); |
|||
sb.AppendLine(" abp switch-to-local --paths D:\\Github\\abp"); |
|||
sb.AppendLine(" abp switch-to-local --paths D:\\Github\\abp --solution D:\\test\\MyProject"); |
|||
sb.AppendLine(" abp switch-to-local --paths \"D:\\Github\\abp|D:\\Github\\volo\""); |
|||
sb.AppendLine("See the documentation for more info: https://docs.abp.io/en/abp/latest/CLI"); |
|||
|
|||
return sb.ToString(); |
|||
} |
|||
|
|||
public static class Options |
|||
{ |
|||
public static class SolutionPath |
|||
{ |
|||
public const string Short = "s"; |
|||
public const string Long = "solution"; |
|||
} |
|||
|
|||
public static class LocalPaths |
|||
{ |
|||
public const string Short = "p"; |
|||
public const string Long = "paths"; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,110 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.IO; |
|||
using System.Threading.Tasks; |
|||
using System.Xml; |
|||
using System.Xml.Linq; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.Extensions.Logging; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.Cli.ProjectModification; |
|||
|
|||
public class LocalReferenceConverter : ITransientDependency |
|||
{ |
|||
|
|||
public ILogger<LocalReferenceConverter> Logger { get; set; } |
|||
|
|||
public async Task ConvertAsync( |
|||
[NotNull] string directory, |
|||
[NotNull] List<string> localPaths) |
|||
{ |
|||
Check.NotNull(directory, nameof(directory)); |
|||
Check.NotNull(localPaths, nameof(localPaths)); |
|||
|
|||
var localProjects = GetLocalProjects(localPaths); |
|||
var targetProjects = Directory.GetFiles(directory, "*.csproj", SearchOption.AllDirectories); |
|||
|
|||
Logger.LogInformation($"Converting projects to local reference."); |
|||
|
|||
foreach (var targetProject in targetProjects) |
|||
{ |
|||
Logger.LogInformation($"Converting to local reference: {targetProject}"); |
|||
|
|||
await ConvertProjectToLocalReferences(targetProject, localProjects); |
|||
} |
|||
|
|||
Logger.LogInformation($"Converted {targetProjects.Length} projects to local references."); |
|||
} |
|||
|
|||
private async Task ConvertProjectToLocalReferences(string targetProject, List<string> localProjects) |
|||
{ |
|||
var xmlDocument = new XmlDocument() { PreserveWhitespace = true }; |
|||
xmlDocument.Load(GenerateStreamFromString(File.ReadAllText(targetProject))); |
|||
|
|||
var matchedNodes = xmlDocument.SelectNodes($"/Project/ItemGroup/PackageReference[@Include]"); |
|||
|
|||
if (matchedNodes == null || matchedNodes.Count == 0) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
foreach (XmlNode matchedNode in matchedNodes) |
|||
{ |
|||
var packageName = matchedNode!.Attributes!["Include"].Value; |
|||
|
|||
var localProject = localProjects.Find(x => |
|||
x.EndsWith($"\\{packageName}.csproj") || |
|||
x.EndsWith($"/{packageName}.csproj") |
|||
); |
|||
|
|||
if (localProject == null) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
var parentNode = matchedNode.ParentNode; |
|||
parentNode!.RemoveChild(matchedNode); |
|||
|
|||
var newNode = xmlDocument.CreateElement("ProjectReference"); |
|||
var includeAttr = xmlDocument.CreateAttribute("Include"); |
|||
includeAttr.Value = CalculateRelativePath(targetProject, localProject); |
|||
newNode.Attributes.Append(includeAttr); |
|||
parentNode.AppendChild(newNode); |
|||
} |
|||
|
|||
File.WriteAllText(targetProject, XDocument.Parse(xmlDocument.OuterXml).ToString()); |
|||
} |
|||
|
|||
private string CalculateRelativePath(string targetProject, string localProject) |
|||
{ |
|||
return new Uri(targetProject).MakeRelativeUri(new Uri(localProject)).ToString(); |
|||
} |
|||
|
|||
private List<string> GetLocalProjects(List<string> localPaths) |
|||
{ |
|||
var list = new List<string>(); |
|||
|
|||
foreach (var localPath in localPaths) |
|||
{ |
|||
if (!Directory.Exists(localPath)) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
list.AddRange(Directory.GetFiles(localPath, "*.csproj", SearchOption.AllDirectories)); |
|||
} |
|||
|
|||
return list; |
|||
} |
|||
|
|||
private MemoryStream GenerateStreamFromString(string s) |
|||
{ |
|||
var stream = new MemoryStream(); |
|||
var writer = new StreamWriter(stream); |
|||
writer.Write(s); |
|||
writer.Flush(); |
|||
stream.Position = 0; |
|||
return stream; |
|||
} |
|||
} |
|||
Loading…
Reference in new issue