Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementing Repository Management actions + Database changes. #3836

Open
wants to merge 46 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
fc754c1
Refining Repository Management's UI. (#3557)
dhoehna Aug 13, 2024
e52afbf
Merge branch 'main' into user/dhoehna/RepositoryManagementFeature
dhoehna Aug 13, 2024
7d00a02
Adding EF core, database project, and some usage. (#3674)
dhoehna Aug 26, 2024
cd2f925
Merge branch 'main' into user/dhoehna/RepositoryManagementFeature
dhoehna Aug 26, 2024
6775301
Merge branch 'user/dhoehna/RepositoryManagementFeature' of https://gi…
dhoehna Aug 26, 2024
9d77f68
Moving this to experimental
dhoehna Aug 26, 2024
17cc488
WIP
dhoehna Aug 27, 2024
66f6978
Some telemetry and logging
dhoehna Aug 27, 2024
8606981
THings build again.
dhoehna Aug 27, 2024
241bcee
Returning this back
dhoehna Aug 27, 2024
234af67
I believe I am understanding this.
dhoehna Aug 28, 2024
038c65b
Can update
dhoehna Aug 28, 2024
e45e669
Almost done with open in FE
dhoehna Aug 28, 2024
0d39cd6
Try/Catching everything. Open in FE should be done.
dhoehna Aug 29, 2024
d6f4f44
Open in CMD works. :)
dhoehna Aug 29, 2024
e3b552e
Merge branch 'main' into user/dhoehna/ImplementingTheRepositoryActions
dhoehna Sep 3, 2024
1d628c7
Re-adding changes lost due to merge
dhoehna Sep 3, 2024
d23a431
Getting saving straightened out.
dhoehna Sep 5, 2024
6b7b72e
Merge branch 'main' into user/dhoehna/ImplementingTheRepositoryActions
dhoehna Sep 5, 2024
d73857d
WIP
dhoehna Sep 5, 2024
87a1a38
Move Repository done.
dhoehna Sep 5, 2024
5395f4c
Removing 1:1. Finishing RemoveFromList
dhoehna Sep 5, 2024
022977a
Adding _items
dhoehna Sep 5, 2024
7fe619c
Adding configuration file information to the repository table
dhoehna Sep 6, 2024
5655157
Opening the configuration file location in FE
dhoehna Sep 6, 2024
2ef3922
Deleting a repository.
dhoehna Sep 6, 2024
2c44c31
Add to winget configuration file.
dhoehna Sep 9, 2024
cfa8f9a
Cleaning up the code
dhoehna Sep 9, 2024
0c00fca
Icon for a configuration file. UI updates when hiding a repo
dhoehna Sep 10, 2024
4135ec4
All the buttons do something.
dhoehna Sep 10, 2024
5d0d7d3
Removing 'local'
dhoehna Sep 10, 2024
e1b38ba
Making sure the test works
dhoehna Sep 11, 2024
9220814
New test works
dhoehna Sep 11, 2024
ce627ce
Another TODO
dhoehna Sep 11, 2024
b8fd941
Fixing more things before PR.
dhoehna Sep 11, 2024
13367f8
Removing another un-used using.
dhoehna Sep 11, 2024
73f6563
MOre un used usings.
dhoehna Sep 11, 2024
cc6f2ba
Another Todo
dhoehna Sep 11, 2024
3441e1c
Anotehr TODO
dhoehna Sep 11, 2024
f30435e
Changing a comment
dhoehna Sep 11, 2024
f674f74
Update database/DevHome.Database/DatabaseModels/RepositoryManagement/…
dhoehna Sep 16, 2024
2a09abe
Comments
dhoehna Sep 16, 2024
689e310
Merge branch 'main' into user/dhoehna/ImplementingTheRepositoryActions
dhoehna Sep 16, 2024
36a9009
Don't just merge code and expect things to work.
dhoehna Sep 16, 2024
fc6fca5
What is in a name?
dhoehna Sep 18, 2024
95bd037
Adressing comments
dhoehna Sep 19, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions common/Services/INavigationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,7 @@ public static class KnownPageKeys
public static readonly string Feedback = "DevHome.Settings.ViewModels.FeedbackViewModel";
public static readonly string Environments = "DevHome.Environments.ViewModels.LandingPageViewModel";
public static readonly string SetupFlow = "DevHome.SetupFlow.ViewModels.SetupFlowViewModel";

// Will not work with navigation service natively. Used for the dictionary in SetupFlowViewModel
public static readonly string RepositoryConfiguration = "RepositoryConfiguration";
dhoehna marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System;
using System.Diagnostics.Tracing;
using DevHome.Telemetry;
using Microsoft.Diagnostics.Telemetry.Internal;

namespace DevHome.Common.TelemetryEvents.DevHomeDatabase;

[EventData]
public class DatabaseContextErrorEvent : EventBase
{
public override PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServicePerformance;

public string Action { get; } = string.Empty;

public int HResult { get; }

public string ExceptionMessage { get; } = string.Empty;

public DatabaseContextErrorEvent(string action)
{
Action = action;
}

public DatabaseContextErrorEvent(string action, Exception ex)
{
Action = action;
HResult = ex.HResult;
ExceptionMessage = ex.Message;
}

public override void ReplaceSensitiveStrings(Func<string, string> replaceSensitiveStrings)
{
// no sensitive strings to replace.
}
}
38 changes: 38 additions & 0 deletions common/TelemetryEvents/DevHomeDatabase/DatabaseEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System;
using System.Diagnostics.Tracing;
using DevHome.Telemetry;
using Microsoft.Diagnostics.Telemetry.Internal;

namespace DevHome.Common.TelemetryEvents.DevHomeDatabase;

[EventData]
public class DatabaseEvent : EventBase
{
public override PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServicePerformance;

public string Step { get; } = string.Empty;

public int HResult { get; }

public string ExceptionMessage { get; } = string.Empty;

public DatabaseEvent(string step)
{
Step = step;
}

public DatabaseEvent(string step, Exception ex)
{
Step = step;
HResult = ex.HResult;
ExceptionMessage = ex.Message;
}

public override void ReplaceSensitiveStrings(Func<string, string> replaceSensitiveStrings)
{
// No sensitive strings to replace.
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.Diagnostics.Tracing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DevHome.Telemetry;
using Microsoft.Diagnostics.Telemetry.Internal;

namespace DevHome.Common.TelemetryEvents.RepositoryManagement;

[EventData]
public class RepositoryDataAccessErrorEvent : EventBase
{
public override PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServicePerformance;

public string Action { get; } = string.Empty;

public int HResult { get; }

public string ErrorMessage { get; } = string.Empty;

public RepositoryDataAccessErrorEvent(string action, int hResult, string errorMessage)
{
Action = action;
HResult = hResult;
ErrorMessage = errorMessage;
}

public override void ReplaceSensitiveStrings(Func<string, string> replaceSensitiveStrings)
{
// No sensative strings to replace
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.Diagnostics.Tracing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DevHome.Telemetry;
using Microsoft.Diagnostics.Telemetry.Internal;

namespace DevHome.Common.TelemetryEvents.RepositoryManagement;

[EventData]
public class RepositoryDataAccessEvent : EventBase
{
public override PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServicePerformance;

public string Action { get; } = string.Empty;

public string Message { get; } = string.Empty;

public RepositoryDataAccessEvent(string action, string message)
{
Action = action;
Message = message;
}

public override void ReplaceSensitiveStrings(Func<string, string> replaceSensitiveStrings)
{
// No sensative strings to replace
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System;
using System.Diagnostics.Tracing;
using DevHome.Telemetry;
using Microsoft.Diagnostics.Telemetry.Internal;

namespace DevHome.Common.TelemetryEvents.RepositoryManagement;

[EventData]
public class RepositoryLineItemErrorEvent : EventBase
{
public override PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServicePerformance;

public string Action { get; } = string.Empty;

public int Hresult { get; }

public string ErrorMessage { get; } = string.Empty;

public string RepositoryName { get; } = string.Empty;

public RepositoryLineItemErrorEvent(string action, int hresult, string errorMessage, string repositoryName)
{
Action = action;
Hresult = hresult;
ErrorMessage = errorMessage;
RepositoryName = repositoryName;
dhoehna marked this conversation as resolved.
Show resolved Hide resolved
}

public override void ReplaceSensitiveStrings(Func<string, string> replaceSensitiveStrings)
{
// No sensitive strings to replace
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.Diagnostics.Tracing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DevHome.Telemetry;
using Microsoft.Diagnostics.Telemetry.Internal;

namespace DevHome.Common.TelemetryEvents.RepositoryManagement;

[EventData]
public class RepositoryLineItemEvent : EventBase
{
public override PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;

public string Action { get; } = string.Empty;

public string RepositoryName { get; } = string.Empty;
dhoehna marked this conversation as resolved.
Show resolved Hide resolved

public RepositoryLineItemEvent(string action, string repositoryName)
{
Action = action;
RepositoryName = repositoryName;
}

public override void ReplaceSensitiveStrings(Func<string, string> replaceSensitiveStrings)
{
// no sensitive strings to replace
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,17 @@ public class Repository

public string? RepositoryClonePath { get; set; }

public bool IsHidden { get; set; }

public bool HasAConfigurationFile => !string.IsNullOrEmpty(ConfigurationFileLocation);

public string? ConfigurationFileLocation { get; set; }

// Use string here. Add-Migration is running into an issue with the Uri class.
// This causes any fluent API statements to get ignored.
public string? RepositoryUri { get; set; }

public DateTime? CreatedUTCDate { get; set; }

public DateTime? UpdatedUTCDate { get; set; }

// 1:1 relationship. Repository is the parent and needs only
// the object of the dependant.
public RepositoryMetadata? RepositoryMetadata { get; set; }
}

This file was deleted.

66 changes: 42 additions & 24 deletions database/DevHome.Database/DevHomeDatabaseContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,39 @@
// Licensed under the MIT License.

using System;
using System.ComponentModel.DataAnnotations.Schema;
using System.IO;
using System.Linq.Expressions;
using DevHome.Common.TelemetryEvents.DevHomeDatabase;
using DevHome.Database.DatabaseModels.RepositoryManagement;
using DevHome.Telemetry;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Serilog;

namespace DevHome.Database;

/// <summary>
/// To make the database please run the following in Package Manager Console
/// Update-Database -StartupProject DevHome.Database -Project DevHome.Database
///
dhoehna marked this conversation as resolved.
Show resolved Hide resolved
/// TODO: Remove this comment after database migration is implemeneted.
/// TODO: Set up Github detection for files in this project.
/// TODO: Add documentation around migration and Entity Framework in DevHome.
/// </summary>
public class DevHomeDatabaseContext : DbContext
{
public DbSet<Repository> Repositories { get; set; }
private const string DatabaseFileName = "DevHome.db";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably add a Const value for this file name/path and add it somewhere central (like config?).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I'm also not a fan of the name "DevHome.db". Mabye something like "DevHomeMachineData.db" to reflect that this is data about what's on the machine (at least that's what I think this is for) :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The database is for all of devhome.

I'll look into making the path, and name const

DevHome.db is for all of DevHome local for every user.

Maybe UserDevHomeData.db?


private readonly ILogger _log = Log.ForContext("SourceContext", nameof(DevHomeDatabaseContext));

public DbSet<RepositoryMetadata> RepositoryMetadatas { get; set; }
public DbSet<Repository> Repositories { get; set; }

public string DbPath { get; }

public DevHomeDatabaseContext()
{
// TODO: make the default path Application data if an MSIX.
// Otherwise use a temp location. Location to be determined later.
var folder = Environment.SpecialFolder.LocalApplicationData;
var path = Environment.GetFolderPath(folder);
DbPath = Path.Join(path, "DevHome.db");
// TODO: How to run the DevHome in VS and not have the file move to the per app location.
DbPath = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), DatabaseFileName);
dhoehna marked this conversation as resolved.
Show resolved Hide resolved
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
Expand All @@ -32,27 +43,34 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
// models using fluent API. Currently, not needed, but will as this method
// will expand as more entities are added.
// If that is too much work these definitions can be placed inside the C# class.
var repositoryEntity = modelBuilder.Entity<Repository>();
if (repositoryEntity != null)
try
{
repositoryEntity.Property(x => x.RepositoryClonePath).HasDefaultValue(string.Empty).IsRequired(true);
repositoryEntity.Property(x => x.RepositoryName).HasDefaultValue(string.Empty).IsRequired(true);
repositoryEntity.Property(x => x.CreatedUTCDate).HasDefaultValueSql("datetime()");
repositoryEntity.Property(x => x.UpdatedUTCDate).HasDefaultValue(new DateTime(1, 1, 1, 0, 0, 0, DateTimeKind.Utc));
repositoryEntity.ToTable("Repository");
// TODO: How to update "UpdatedAt"?
var repositoryEntity = modelBuilder.Entity<Repository>();
if (repositoryEntity != null)
{
repositoryEntity.Property(x => x.ConfigurationFileLocation).HasDefaultValue(string.Empty);
repositoryEntity.Property(x => x.RepositoryClonePath).HasDefaultValue(string.Empty).IsRequired(true);
repositoryEntity.Property(x => x.RepositoryName).HasDefaultValue(string.Empty).IsRequired(true);
repositoryEntity.Property(x => x.CreatedUTCDate).HasDefaultValueSql("datetime()");
repositoryEntity.Property(x => x.UpdatedUTCDate).HasDefaultValueSql("datetime()");
repositoryEntity.Property(x => x.RepositoryUri).HasDefaultValue(string.Empty);
repositoryEntity.ToTable("Repository");
}
}

var repositoryMetadataEntity = modelBuilder.Entity<RepositoryMetadata>();
if (repositoryMetadataEntity != null)
catch (Exception ex)
{
repositoryMetadataEntity.Property(x => x.IsHiddenFromPage).HasDefaultValue(false).IsRequired(true);
repositoryMetadataEntity.Property(x => x.UtcDateHidden).HasDefaultValue(new DateTime(1, 1, 1, 0, 0, 0, DateTimeKind.Utc)).IsRequired(true);
repositoryMetadataEntity.Property(x => x.CreatedUTCDate).HasDefaultValueSql("datetime()");
repositoryMetadataEntity.Property(x => x.UpdatedUTCDate).HasDefaultValue(new DateTime(1, 1, 1, 0, 0, 0, DateTimeKind.Utc));
repositoryMetadataEntity.ToTable("RepositoryMetadata");
// TODO: Notify user the database could not initialize.
_log.Error(ex, "Can not build the database model");
TelemetryFactory.Get<ITelemetry>().Log(
"DevHome_DatabaseContext_Event",
LogLevel.Critical,
new DatabaseContextErrorEvent("CreatingModel", ex));
}
}

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.UseSqlite($"Data Source={DbPath}");
{
optionsBuilder.UseSqlite($"Data Source={DbPath}");
}
}
Loading