diff --git a/src/Microsoft.Framework.PackageManager/Packing/PackManager.cs b/src/Microsoft.Framework.PackageManager/Packing/PackManager.cs index 77308ec12..6a86692da 100644 --- a/src/Microsoft.Framework.PackageManager/Packing/PackManager.cs +++ b/src/Microsoft.Framework.PackageManager/Packing/PackManager.cs @@ -113,8 +113,6 @@ public bool Package() var root = new PackRoot(project, outputPath) { Overwrite = _options.Overwrite, - ZipPackages = _options.ZipPackages, - AppFolder = _options.AppFolder ?? project.Name, Configuration = _options.Configuration, NoSource = _options.NoSource }; diff --git a/src/Microsoft.Framework.PackageManager/Packing/PackOptions.cs b/src/Microsoft.Framework.PackageManager/Packing/PackOptions.cs index dc9d9d09f..13131cb1c 100644 --- a/src/Microsoft.Framework.PackageManager/Packing/PackOptions.cs +++ b/src/Microsoft.Framework.PackageManager/Packing/PackOptions.cs @@ -18,8 +18,6 @@ public class PackOptions public FrameworkName RuntimeTargetFramework { get; set; } - public bool ZipPackages { get; set; } - public bool Overwrite { get; set; } public bool NoSource { get; set; } diff --git a/src/Microsoft.Framework.PackageManager/Packing/PackProject.cs b/src/Microsoft.Framework.PackageManager/Packing/PackProject.cs index b2317ef04..18cae768e 100644 --- a/src/Microsoft.Framework.PackageManager/Packing/PackProject.cs +++ b/src/Microsoft.Framework.PackageManager/Packing/PackProject.cs @@ -41,7 +41,7 @@ public void EmitSource(PackRoot root) throw new Exception("TODO: unable to resolve project named " + _libraryDescription.Identity.Name); } - var targetName = AppFolder ?? project.Name; + var targetName = project.Name; TargetPath = Path.Combine(root.OutputPath, PackRoot.AppRootName, "src", targetName); Console.WriteLine(" Source {0}", project.ProjectDirectory); @@ -49,17 +49,12 @@ public void EmitSource(PackRoot root) root.Operations.Delete(TargetPath); - // A set of excluded source files used as a filter when doing copy - var sourceExcludeFiles = new HashSet(project.SourceExcludeFiles, StringComparer.OrdinalIgnoreCase); + // A set of excluded files used as a filter when doing copy + var excludeFiles = new HashSet(project.ExcludeFiles, StringComparer.OrdinalIgnoreCase); root.Operations.Copy(project.ProjectDirectory, TargetPath, (isRoot, filePath) => { - if (IsImplicitlyExcludedFile(filePath)) - { - return false; - } - - if (sourceExcludeFiles.Contains(filePath)) + if (excludeFiles.Contains(filePath)) { return false; } @@ -78,7 +73,7 @@ public void EmitNupkg(PackRoot root) throw new Exception("TODO: unable to resolve project named " + _libraryDescription.Identity.Name); } - var targetName = AppFolder ?? project.Name; + var targetName = project.Name; var targetNupkgName = string.Format("{0}.{1}", targetName, project.Version); TargetPath = Path.Combine(root.OutputPath, PackRoot.AppRootName, "packages", targetNupkgName); @@ -132,28 +127,29 @@ public void EmitNupkg(PackRoot root) } } - private static bool IsImplicitlyExcludedFile(string filePath) + public void PostProcess(PackRoot root) { - var fileExtension = Path.GetExtension(filePath); - var fileName = Path.GetFileName(filePath); - - if (string.Equals(fileExtension, ".csproj", StringComparison.OrdinalIgnoreCase) || - string.Equals(fileExtension, ".kproj", StringComparison.OrdinalIgnoreCase) || - string.Equals(fileExtension, ".user", StringComparison.OrdinalIgnoreCase) || - string.Equals(fileExtension, ".vspscc", StringComparison.OrdinalIgnoreCase) || - string.Equals(fileExtension, ".vssscc", StringComparison.OrdinalIgnoreCase) || - string.Equals(fileExtension, ".pubxml", StringComparison.OrdinalIgnoreCase) || - string.Equals(fileName, "bin", StringComparison.OrdinalIgnoreCase) || - string.Equals(fileName, "obj", StringComparison.OrdinalIgnoreCase)) + Project project; + if (!_projectResolver.TryResolveProject(_libraryDescription.Identity.Name, out project)) { - return true; + throw new Exception("TODO: unable to resolve project named " + _libraryDescription.Identity.Name); } - return false; - } - public void PostProcess(PackRoot root) - { - var binFolderPath = Path.Combine(TargetPath, "bin"); + // Construct path to public app folder, which contains content files and tool dlls + // The name of public app folder is specified with "--appfolder" option + // Default name of public app folder is the same as main project + var appFolderName = AppFolder ?? PackRoot.DefaultAppFolderName; + var appFolderPath = Path.Combine(root.OutputPath, appFolderName); + + // Delete old public app folder because we don't want leftovers from previous operations + root.Operations.Delete(appFolderPath); + Directory.CreateDirectory(appFolderPath); + + // Copy content files (e.g. html, js and images) of main project into public app folder + CopyContentFiles(root, project, appFolderName); + + // Tool dlls including AspNet.Loader.dll go to bin folder under public app folder + var appFolderBinPath = Path.Combine(appFolderPath, "bin"); var defaultRuntime = root.Runtimes.FirstOrDefault(); var iniFilePath = Path.Combine(TargetPath, "k.ini"); @@ -179,6 +175,18 @@ public void PostProcess(PackRoot root) } } + // Generate k.ini for public app folder + var appFolderIniFilePath = Path.Combine(appFolderPath, "k.ini"); + var appBaseLine = string.Format("APP_BASE={0}", + Path.Combine("..", PackRoot.AppRootName, "src", project.Name)); + var iniContents = string.Empty; + if (File.Exists(iniFilePath)) + { + iniContents = File.ReadAllText(iniFilePath); + } + File.WriteAllText(appFolderIniFilePath, + string.Format("{0}{1}", iniContents, appBaseLine)); + // Copy tools/*.dll into bin to support AspNet.Loader.dll foreach (var package in root.Packages) { @@ -187,74 +195,51 @@ public void PostProcess(PackRoot root) { foreach (var packageToolFile in Directory.EnumerateFiles(packageToolsPath, "*.dll").Select(Path.GetFileName)) { - if (!Directory.Exists(binFolderPath)) + if (!Directory.Exists(appFolderBinPath)) { - Directory.CreateDirectory(binFolderPath); + Directory.CreateDirectory(appFolderBinPath); } + // Copy to bin folder under public app folder File.Copy( Path.Combine(packageToolsPath, packageToolFile), - Path.Combine(binFolderPath, packageToolFile), + Path.Combine(appFolderBinPath, packageToolFile), true); } } } + } + + private void CopyContentFiles(PackRoot root, Project project, string appFolderName) + { + Console.WriteLine("Copying contents of project dependency {0} to {1}", + _libraryDescription.Identity.Name, appFolderName); - // Copy lib/**/*.dll into bin/$xxxxxxx.packages to support web deploy - if (root.ZipPackages) + var appFolderPath = Path.Combine(root.OutputPath, appFolderName); + + Console.WriteLine(" Source {0}", project.ProjectDirectory); + Console.WriteLine(" Target {0}", appFolderPath); + + // A set of content files that should be copied + var contentFiles = new HashSet(project.ContentFiles, StringComparer.OrdinalIgnoreCase); + + root.Operations.Copy(project.ProjectDirectory, appFolderPath, (isRoot, filePath) => { - if (!Directory.Exists(binFolderPath)) + // We always explore a directory + if (Directory.Exists(filePath)) { - Directory.CreateDirectory(binFolderPath); + return true; } - var chars = "abcdefghijklmnopqrstuvwxyz0123456789"; - var rnd = new Random(); - var sequence = new string(Enumerable.Range(0, 7).Select(_ => chars[rnd.Next(chars.Length)]).ToArray()); - var targetFile = Path.Combine(binFolderPath, "$" + sequence + ".packages"); - - using (var targetStream = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None)) + var fileName = Path.GetFileName(filePath); + // Public app folder doesn't need project.json + if (string.Equals(fileName, "project.json", StringComparison.OrdinalIgnoreCase)) { - using (var archive = new ZipArchive(targetStream, ZipArchiveMode.Create)) - { - foreach (var package in root.Packages) - { - root.Operations.AddFiles( - archive, - package.TargetPath, - Path.Combine("packages", package.Library.Name + "." + package.Library.Version), - IncludePackageFileInBundle); - } - foreach (var runtime in root.Runtimes) - { - //root.Operations.AddFiles( - // archive, - // root.Runtime.TargetPath, - // Path.Combine("packages", root.Runtime.Name + "." + root.Runtime.Version), - // IncludeRuntimeFileInBundle); - } - } + return false; } - } - } - - private bool IncludePackageFileInBundle(string relativePath, string fileName) - { - var fileExtension = Path.GetExtension(fileName); - var rootFolder = BasePath(relativePath); - if (/*string.Equals(rootFolder, "lib", StringComparison.OrdinalIgnoreCase) && */ - string.Equals(fileExtension, ".dll", StringComparison.OrdinalIgnoreCase)) - { - return true; - } - if (string.IsNullOrEmpty(relativePath) && - (string.Equals(fileExtension, ".sha512", StringComparison.OrdinalIgnoreCase) || - string.Equals(fileExtension, ".nuspec", StringComparison.OrdinalIgnoreCase))) - { - return true; - } - return false; + return contentFiles.Contains(filePath); + }); } private bool IncludeRuntimeFileInBundle(string relativePath, string fileName) diff --git a/src/Microsoft.Framework.PackageManager/Packing/PackRoot.cs b/src/Microsoft.Framework.PackageManager/Packing/PackRoot.cs index d5d8182e4..39e34ebc4 100644 --- a/src/Microsoft.Framework.PackageManager/Packing/PackRoot.cs +++ b/src/Microsoft.Framework.PackageManager/Packing/PackRoot.cs @@ -15,6 +15,7 @@ public class PackRoot { private readonly Runtime.Project _project; public static readonly string AppRootName = "approot"; + public static readonly string DefaultAppFolderName = "public"; public PackRoot(Runtime.Project project, string outputPath) { @@ -30,9 +31,7 @@ public PackRoot(Runtime.Project project, string outputPath) public string OutputPath { get; private set; } public string PackagesPath { get; private set; } - public string AppFolder { get; set; } public bool Overwrite { get; set; } - public bool ZipPackages { get; set; } public bool NoSource { get; set; } public string Configuration { get; set; } @@ -96,13 +95,13 @@ public void Emit() { File.WriteAllText( Path.Combine(OutputPath, commandName + ".cmd"), - string.Format(template1, commandName, Path.Combine(AppRootName, "src", AppFolder ?? _project.Name), Runtimes.First().Name)); + string.Format(template1, commandName, Path.Combine(AppRootName, "src", _project.Name), Runtimes.First().Name)); } else { File.WriteAllText( Path.Combine(OutputPath, commandName + ".cmd"), - string.Format(template2, commandName, Path.Combine(AppRootName, "src", AppFolder ?? _project.Name))); + string.Format(template2, commandName, Path.Combine(AppRootName, "src", _project.Name))); } } } diff --git a/src/Microsoft.Framework.PackageManager/Program.cs b/src/Microsoft.Framework.PackageManager/Program.cs index aa7b025c8..1dad30562 100644 --- a/src/Microsoft.Framework.PackageManager/Program.cs +++ b/src/Microsoft.Framework.PackageManager/Program.cs @@ -142,8 +142,6 @@ public int Main(string[] args) var argProject = c.Argument("[project]", "Path to project, default is current directory"); var optionOut = c.Option("-o|--out ", "Where does it go", CommandOptionType.SingleValue); var optionConfiguration = c.Option("--configuration ", "The configuration to use for deployment", CommandOptionType.SingleValue); - var optionZipPackages = c.Option("-z|--zippackages", "Bundle a zip full of packages", - CommandOptionType.NoValue); var optionOverwrite = c.Option("--overwrite", "Remove existing files in target folders", CommandOptionType.NoValue); var optionNoSource = c.Option("--no-source", "Don't include sources of project dependencies", @@ -156,10 +154,9 @@ public int Main(string[] args) c.OnExecute(() => { - Console.WriteLine("verbose:{0} out:{1} zip:{2} project:{3}", + Console.WriteLine("verbose:{0} out:{1} project:{2}", optionVerbose.HasValue(), optionOut.Value(), - optionZipPackages.HasValue(), argProject.Value); var options = new PackOptions @@ -169,7 +166,6 @@ public int Main(string[] args) AppFolder = optionAppFolder.Value(), Configuration = optionConfiguration.Value() ?? "debug", RuntimeTargetFramework = _environment.TargetFramework, - ZipPackages = optionZipPackages.HasValue(), Overwrite = optionOverwrite.HasValue(), NoSource = optionNoSource.HasValue(), Runtimes = optionRuntime.HasValue() ? diff --git a/src/Microsoft.Framework.Runtime/Project.cs b/src/Microsoft.Framework.Runtime/Project.cs index 1b7136758..4b586ad12 100644 --- a/src/Microsoft.Framework.Runtime/Project.cs +++ b/src/Microsoft.Framework.Runtime/Project.cs @@ -19,10 +19,12 @@ public class Project private static readonly char[] _sourceSeparator = new[] { ';' }; internal static readonly string[] _defaultSourcePatterns = new[] { @"**\*.cs" }; - internal static readonly string[] _defaultSourceExcludePatterns = new[] { @"obj\**\*", @"bin\**\*" }; + internal static readonly string[] _defaultExcludePatterns = new[] { @"obj\**\*", @"bin\**\*", @"**.csproj", + @"**.kproj", @"**.user", @"**.vspscc", @"**.vssscc", @"**.pubxml" }; internal static readonly string[] _defaultPreprocessPatterns = new[] { @"compiler\preprocess\**\*.cs" }; internal static readonly string[] _defaultSharedPatterns = new[] { @"compiler\shared\**\*.cs" }; internal static readonly string[] _defaultResourcesPatterns = new[] { @"compiler\resources\**\*" }; + internal static readonly string[] _defaultContentsPatterns = new[] { @"**\*" }; private readonly Dictionary _targetFrameworks = new Dictionary(); private readonly Dictionary _compilationOptions = new Dictionary(); @@ -63,7 +65,7 @@ public string ProjectDirectory internal IEnumerable SourcePatterns { get; set; } - internal IEnumerable SourceExcludePatterns { get; set; } + internal IEnumerable ExcludePatterns { get; set; } internal IEnumerable PreprocessPatterns { get; set; } @@ -71,6 +73,8 @@ public string ProjectDirectory internal IEnumerable ResourcesPatterns { get; set; } + internal IEnumerable ContentsPatterns { get; set; } + public IEnumerable SourceFiles { get @@ -83,7 +87,7 @@ public IEnumerable SourceFiles .SelectMany(pattern => PathResolver.PerformWildcardSearch(path, pattern)) .ToArray(); - var excludePatterns = PreprocessPatterns.Concat(SharedPatterns).Concat(ResourcesPatterns).Concat(SourceExcludePatterns) + var excludePatterns = PreprocessPatterns.Concat(SharedPatterns).Concat(ResourcesPatterns).Concat(ExcludePatterns) .Select(pattern => PathResolver.NormalizeWildcardForExcludedFiles(path, pattern)) .ToArray(); @@ -94,13 +98,13 @@ public IEnumerable SourceFiles } } - public IEnumerable SourceExcludeFiles + public IEnumerable ExcludeFiles { get { string path = ProjectDirectory; - var sourceExcludeFiles = SourceExcludePatterns + var sourceExcludeFiles = ExcludePatterns .SelectMany(pattern => PathResolver.PerformWildcardSearch(path, pattern)) .ToArray(); @@ -136,6 +140,28 @@ public IEnumerable SharedFiles } } + public IEnumerable ContentFiles + { + get + { + string path = ProjectDirectory; + + var includeFiles = ContentsPatterns + .SelectMany(pattern => PathResolver.PerformWildcardSearch(path, pattern)) + .ToArray(); + + var excludePatterns = PreprocessPatterns.Concat(SharedPatterns).Concat(ResourcesPatterns) + .Concat(ExcludePatterns).Concat(SourcePatterns) + .Select(pattern => PathResolver.NormalizeWildcardForExcludedFiles(path, pattern)) + .ToArray(); + + var excludeFiles = PathResolver.GetMatches(includeFiles, x => x, excludePatterns) + .ToArray(); + + return includeFiles.Except(excludeFiles).Distinct().ToArray(); + } + } + public IDictionary Commands { get; private set; } public IEnumerable GetTargetFrameworks() @@ -207,10 +233,11 @@ public static Project GetProject(string json, string projectName, string project // Source file patterns project.SourcePatterns = GetSourcePattern(rawProject, "code", _defaultSourcePatterns); - project.SourceExcludePatterns = GetSourcePattern(rawProject, "exclude", _defaultSourceExcludePatterns); + project.ExcludePatterns = GetSourcePattern(rawProject, "exclude", _defaultExcludePatterns); project.PreprocessPatterns = GetSourcePattern(rawProject, "preprocess", _defaultPreprocessPatterns); project.SharedPatterns = GetSourcePattern(rawProject, "shared", _defaultSharedPatterns); project.ResourcesPatterns = GetSourcePattern(rawProject, "resources", _defaultResourcesPatterns); + project.ContentsPatterns = GetSourcePattern(rawProject, "files", _defaultContentsPatterns); // Set the default loader information for projects var loaderAssemblyName = "Microsoft.Framework.Runtime.Roslyn"; diff --git a/test/Microsoft.Framework.Runtime.Tests/ProjectFacts.cs b/test/Microsoft.Framework.Runtime.Tests/ProjectFacts.cs index 6e9988074..710cdbf98 100644 --- a/test/Microsoft.Framework.Runtime.Tests/ProjectFacts.cs +++ b/test/Microsoft.Framework.Runtime.Tests/ProjectFacts.cs @@ -145,7 +145,7 @@ public void SourcePatternsAreSet() @"c:\foo\project.json"); Assert.Equal(new[] { "*.cs", @"../*.cs" }, project.SourcePatterns); - Assert.Equal(new[] { @"buggy/*.*" }, project.SourceExcludePatterns); + Assert.Equal(new[] { @"buggy/*.*" }, project.ExcludePatterns); Assert.Equal(new[] { @"other/**/*.cs", "*.cs", "*.*" }, project.PreprocessPatterns); Assert.Equal(new[] { @"shared/**/*.cs" }, project.SharedPatterns); Assert.Equal(new[] { "a.cs", @"foo.js" }, project.ResourcesPatterns); @@ -166,7 +166,7 @@ public void SourcePatternsWorkForArraysAreSet() @"c:\foo\project.json"); Assert.Equal(new[] { "*.cs", @"../*.cs" }, project.SourcePatterns); - Assert.Equal(new[] { @"buggy/*.*" }, project.SourceExcludePatterns); + Assert.Equal(new[] { @"buggy/*.*" }, project.ExcludePatterns); Assert.Equal(new[] { @"other/**/*.cs", "*.cs", "*.*" }, project.PreprocessPatterns); Assert.Equal(new[] { @"shared/**/*.cs", @"../../shared/*.cs" }, project.SharedPatterns); Assert.Equal(new[] { "a.cs", @"foo.js" }, project.ResourcesPatterns); @@ -182,7 +182,7 @@ public void DefaultSourcePatternsAreUsedIfNoneSpecified() @"c:\foo\project.json"); Assert.Equal(Project._defaultSourcePatterns, project.SourcePatterns); - Assert.Equal(Project._defaultSourceExcludePatterns, project.SourceExcludePatterns); + Assert.Equal(Project._defaultExcludePatterns, project.ExcludePatterns); Assert.Equal(Project._defaultPreprocessPatterns, project.PreprocessPatterns); Assert.Equal(Project._defaultSharedPatterns, project.SharedPatterns); Assert.Equal(Project._defaultResourcesPatterns, project.ResourcesPatterns); @@ -213,7 +213,7 @@ public void EmptyStringAndNullElementsAreIgnored() @"c:\foo\project.json"); Assert.Equal(new[] { "a.cs", "b.cs", "c.cs" }, project.SourcePatterns); - Assert.Equal(new[] { "a.cs" }, project.SourceExcludePatterns); + Assert.Equal(new[] { "a.cs" }, project.ExcludePatterns); } } }