Skip to content

Commit

Permalink
Merge branch 'release' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
pranavkm committed May 7, 2016
2 parents 3440b38 + 96628d5 commit 2a7c122
Show file tree
Hide file tree
Showing 11 changed files with 127 additions and 20 deletions.
2 changes: 2 additions & 0 deletions src/Microsoft.EntityFrameworkCore.Tools.Cli/ExecuteCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ public static CommandLineApplication Create()
{
var app = new CommandLineApplication()
{
// Technically, the real "dotnet-ef.dll" is in Microsoft.EntityFrameworkCore.Tools,
// but this name is what the help usage displays
Name = "dotnet ef",
FullName = "Entity Framework .NET Core CLI Commands"
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public static void Configure([NotNull] CommandLineApplication command, [NotNull]

var outputDir = command.Option(
"-o|--output-dir <path>",
"The directory (and sub-namespace) to use. If omitted, \"Migrations\" is used.");
"The directory (and sub-namespace) to use. If omitted, \"Migrations\" is used. Relative paths are relative the directory in which the command is executed.");
var context = command.Option(
"-c|--context <context>",
"The DbContext to use. If omitted, the default DbContext is used");
Expand Down
11 changes: 10 additions & 1 deletion src/Microsoft.EntityFrameworkCore.Tools.Cli/OperationExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,16 @@ public virtual MigrationFiles AddMigration(
[NotNull] string name,
[CanBeNull] string outputDir,
[CanBeNull] string contextType)
=> _migrationsOperations.Value.AddMigration(name, outputDir, contextType);
{
if(!string.IsNullOrWhiteSpace(outputDir) && !Path.IsPathRooted(outputDir))
{
// relative paths adjusted to current working directory, not project directory
// PowerShell adjusts the cwd when executing dotnet-ef.
outputDir = Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), outputDir));
}

return _migrationsOperations.Value.AddMigration(name, outputDir, contextType);
}

public virtual void UpdateDatabase([CanBeNull] string targetMigration, [CanBeNull] string contextType)
=> _migrationsOperations.Value.UpdateDatabase(targetMigration, contextType);
Expand Down
4 changes: 2 additions & 2 deletions src/Microsoft.EntityFrameworkCore.Tools.Cli/project.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"version": "1.0.0-*",
"description": "Entity Framework Core Commands for .NET Core CLI on .NET 4.5.1",
"version": "1.0.0-preview1-*",
"description": "Components for Entity Framework Commands on .NET Core CLI",
"buildOptions": {
"emitEntryPoint": true,
"warningsAsErrors": true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,8 @@ public virtual MigrationFiles AddMigration(
{
Check.NotEmpty(name, nameof(name));

var subNamespace = outputDir != null
? string.Join(".", outputDir.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar))
: null;
outputDir = string.IsNullOrWhiteSpace(outputDir) ? null : outputDir;
var subNamespace = SubnamespaceFromOutputPath(outputDir);

using (var context = _contextOperations.CreateContext(contextType))
{
Expand All @@ -88,6 +87,23 @@ public virtual MigrationFiles AddMigration(
}
}

// if outputDir is a subfolder of projectDir, then use each subfolder as a subnamespace
// --output-dir $(projectFolder)/A/B/C
// => "namespace $(rootnamespace).A.B.C"
private string SubnamespaceFromOutputPath(string outputDir)
{
if (outputDir == null || !outputDir.StartsWith(_projectDir))
{
return null;
}

var subPath = outputDir.Substring(_projectDir.Length);

return !string.IsNullOrWhiteSpace(subPath)
? string.Join(".", subPath.Split(new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries))
: null;
}

public virtual IEnumerable<MigrationInfo> GetMigrations(
[CanBeNull] string contextType)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -302,8 +302,8 @@ public virtual MigrationFiles RemoveMigration([NotNull] string projectDir, [NotN
}

public virtual MigrationFiles Save(
[NotNull] string projectDir,
[NotNull] ScaffoldedMigration migration,
[NotNull] string projectDir,
[NotNull] ScaffoldedMigration migration,
[CanBeNull] string outputDir)
{
Check.NotEmpty(projectDir, nameof(projectDir));
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,9 @@
<value>Root namespace of the project is required to generate code.</value>
</data>
<data name="MigrationsAssemblyMismatch" xml:space="preserve">
<value>Your target project '{assembly}' doesn't match your migrations assembly '{migrationsAssembly}'. Change your target project to the migrations project by using the Package Manager Console's Default project drop-down list. Change your migrations assembly by using DbContextOptionsBuilder. E.g. options.UseSqlServer(connection, b =&gt; b.MigrationsAssembly("{assembly}"))</value>
<value>Your target project '{assembly}' doesn't match your migrations assembly '{migrationsAssembly}'. Either change your target project or change your migrations assembly.
Change your migrations assembly by using DbContextOptionsBuilder. E.g. options.UseSqlServer(connection, b =&gt; b.MigrationsAssembly("{assembly}")). By default, the migrations assembly is the assembly containing the DbContext.
Change your target project to the migrations project by using the Package Manager Console's Default project drop-down list, or by executing "dotnet ef" from the directory containing the migrations project.</value>
</data>
<data name="SensitiveInformationWarning" xml:space="preserve">
<value>To protect potentially sensitive information in your connection string, you should move it out of source code. See http://go.microsoft.com/fwlink/?LinkId=723263 for guidance on storing connection strings.</value>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using Microsoft.EntityFrameworkCore.Design.Internal;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Utilities;
using System.IO;

namespace Microsoft.EntityFrameworkCore.Design
{
Expand All @@ -21,6 +22,7 @@ public partial class OperationExecutor
private readonly LazyRef<DbContextOperations> _contextOperations;
private readonly LazyRef<DatabaseOperations> _databaseOperations;
private readonly LazyRef<MigrationsOperations> _migrationsOperations;
private readonly string _projectDir;

public OperationExecutor([NotNull] object logHandler, [NotNull] IDictionary args)
: this(logHandler, args, new AssemblyLoader())
Expand All @@ -39,7 +41,7 @@ public OperationExecutor([NotNull] object logHandler, [NotNull] IDictionary args
var targetName = (string)args["targetName"];
var startupTargetName = (string)args["startupTargetName"];
var environment = (string)args["environment"];
var projectDir = (string)args["projectDir"];
_projectDir = (string)args["projectDir"];
var startupProjectDir = (string)args["startupProjectDir"];
var rootNamespace = (string)args["rootNamespace"];

Expand Down Expand Up @@ -73,7 +75,7 @@ public OperationExecutor([NotNull] object logHandler, [NotNull] IDictionary args
assemblyLoader,
startupAssembly.Value,
environment,
projectDir,
_projectDir,
startupProjectDir,
rootNamespace));
_migrationsOperations = new LazyRef<MigrationsOperations>(
Expand All @@ -83,7 +85,7 @@ public OperationExecutor([NotNull] object logHandler, [NotNull] IDictionary args
assemblyLoader,
startupAssembly.Value,
environment,
projectDir,
_projectDir,
startupProjectDir,
rootNamespace));
}
Expand Down Expand Up @@ -134,6 +136,12 @@ private IDictionary AddMigrationImpl(
{
Check.NotEmpty(name, nameof(name));

// In package manager console, relative outputDir is relative to project directory
if (!string.IsNullOrWhiteSpace(outputDir) && !Path.IsPathRooted(outputDir))
{
outputDir = Path.GetFullPath(Path.Combine(_projectDir, outputDir));
}

var files = _migrationsOperations.Value.AddMigration(
name,
outputDir,
Expand Down
18 changes: 14 additions & 4 deletions src/Microsoft.EntityFrameworkCore.Tools/tools/EntityFramework.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ Register-TabExpansion Add-Migration @{
Context = { param ($tabExpansionContext) GetContextTypes $tabExpansionContext.Project $tabExpansionContext.StartupProject $tabExpansionContext.Environment }
Project = { GetProjects }
StartupProject = { GetProjects }
# disables tab completion on output dir
OutputDir = { }
}

<#
Expand All @@ -87,7 +89,7 @@ Register-TabExpansion Add-Migration @{
Specifies the name of the migration.
.PARAMETER OutputDir
The directory (and sub-namespace) to use. If omitted, "Migrations" is used.
The directory (and sub-namespace) to use. If omitted, "Migrations" is used. Relative paths are relative to project directory.
.PARAMETER Context
Specifies the DbContext to use. If omitted, the default DbContext is used.
Expand Down Expand Up @@ -129,15 +131,23 @@ function Add-Migration {
}
$files = InvokeDotNetEf $dteProject -json migrations add $Name @options
$DTE.ItemOperations.OpenFile($files.MigrationFile) | Out-Null
} else {
}
else {
$artifacts = InvokeOperation $dteStartupProject $Environment $dteProject AddMigration @{
name = $Name
outputDir = $OutputDir
contextType = $contextTypeName
}

$dteProject.ProjectItems.AddFromFile($artifacts.MigrationFile) | Out-Null
$dteProject.ProjectItems.AddFromFile($artifacts.MetadataFile) | Out-Null

try {
$dteProject.ProjectItems.AddFromFile($artifacts.MetadataFile) | Out-Null
} catch {
# in some SKUs the call to add MigrationFile will automatically add the MetadataFile because it is named ".Designer.cs"
# this will throw a non fatal error when -OutputDir is outside the main project directory
}

$dteProject.ProjectItems.AddFromFile($artifacts.SnapshotFile) | Out-Null
$DTE.ItemOperations.OpenFile($artifacts.MigrationFile) | Out-Null
ShowConsole
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using Microsoft.EntityFrameworkCore.Tools.Core.FunctionalTests.TestUtilities;
using Microsoft.EntityFrameworkCore.Tools.FunctionalTests.TestUtilities;
using Xunit;
using System.Collections;

namespace Microsoft.EntityFrameworkCore.Tools.FunctionalTests.Design
{
Expand All @@ -35,15 +36,72 @@ public void GetContextType_works_cross_domain()
Assert.StartsWith("SimpleProject.SimpleContext, ", contextTypeName);
}

private void AssertDefaultMigrationName(IDictionary artifacts)
{
Assert.Contains("namespace SimpleProject.Migrations", File.ReadAllText(artifacts["MigrationFile"] as string));
}

[ConditionalFact]
public void AddMigration_works_cross_domain()
{
var artifacts = _project.Executor.AddMigration("EmptyMigration", "Migrationz", "SimpleContext");
var artifacts = _project.Executor.AddMigration("EmptyMigration", "CustomFolder", "SimpleContext");
Assert.NotNull(artifacts);
Assert.NotNull(artifacts["MigrationFile"]);
Assert.NotNull(artifacts["MetadataFile"]);
Assert.NotNull(artifacts["SnapshotFile"]);
Assert.True(Directory.Exists("Migrationz"));
Assert.True(Directory.Exists(Path.Combine(_project.TargetDir, "CustomFolder")));
Assert.Contains("namespace SimpleProject.CustomFolder", File.ReadAllText(artifacts["MigrationFile"] as string));
}

[ConditionalFact]
public void AddMigration_output_dir_relative_to_projectdir()
{
var artifacts = _project.Executor.AddMigration("EmptyMigration1", "./CustomFolder", "SimpleContext");
Assert.NotNull(artifacts);
Assert.StartsWith(Path.Combine(_project.TargetDir, "CustomFolder"), artifacts["MigrationFile"] as string);
Assert.Contains("namespace SimpleProject.CustomFolder", File.ReadAllText(artifacts["MigrationFile"] as string));
}

[ConditionalFact]
public void AddMigration_output_dir_relative_out_of_to_projectdir()
{
var artifacts = _project.Executor.AddMigration("EmptyMigration1", "../CustomFolder", "SimpleContext");
Assert.NotNull(artifacts);
Assert.StartsWith(Path.GetFullPath(Path.Combine(_project.TargetDir, "../CustomFolder")), artifacts["MigrationFile"] as string);
AssertDefaultMigrationName(artifacts);
}


[ConditionalFact]
public void AddMigration_output_dir_absolute_path_in_project()
{
var outputDir = Path.Combine(_project.TargetDir, "A/B/C");
var artifacts = _project.Executor.AddMigration("EmptyMigration1", outputDir, "SimpleContext");
Assert.NotNull(artifacts);
Assert.Equal(Path.Combine(outputDir, Path.GetFileName(artifacts["MigrationFile"] as string)), artifacts["MigrationFile"]);
Assert.Contains("namespace SimpleProject.A.B.C", File.ReadAllText(artifacts["MigrationFile"] as string));
}

[ConditionalFact]
public void AddMigration_output_dir_absolute_path_outside_project()
{
var outputDir = Path.GetTempPath();
var artifacts = _project.Executor.AddMigration("EmptyMigration1", outputDir, "SimpleContext");
Assert.NotNull(artifacts);
Assert.StartsWith(outputDir, artifacts["MigrationFile"] as string);
AssertDefaultMigrationName(artifacts);
}

[ConditionalTheory]
[InlineData("")]
[InlineData(" ")]
[InlineData(null)]
public void AddMigration_handles_empty_output_dir(string outputDir)
{
var artifacts = _project.Executor.AddMigration("EmptyMigration2", outputDir, "SimpleContext");
Assert.NotNull(artifacts);
Assert.StartsWith(Path.Combine(_project.TargetDir, "Migrations"), artifacts["MigrationFile"] as string);
AssertDefaultMigrationName(artifacts);
}

[ConditionalFact]
Expand Down

0 comments on commit 2a7c122

Please sign in to comment.