Skip to content
This repository was archived by the owner on Jun 5, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 56 commits
Commits
Show all changes
63 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
42f7605
Localized strings
dhoehna Sep 11, 2024
e7444d1
WIP
dhoehna Sep 12, 2024
3c24c6a
Merge branch 'main' into user/dhoehna/DatabaseMigrationsAndTodos
dhoehna Sep 12, 2024
203070f
Adding enhanced information if it can be found.
dhoehna Sep 13, 2024
bf9edb7
Commit, Filtering, and Sorting.
dhoehna Sep 14, 2024
e72aa44
Merge
dhoehna Sep 20, 2024
1fbf56c
Fixing up the merge
dhoehna Sep 20, 2024
6eb1145
Removing Move/Delete because of a bug in FileExplorerGitIntegration.
dhoehna Sep 23, 2024
ed70a2f
Adding a TODO
dhoehna Sep 23, 2024
5d93aff
A small commit
dhoehna Sep 23, 2024
2c21807
Removing some unused usings
dhoehna Sep 23, 2024
5b7dd87
Update tools/RepositoryManagement/DevHome.RepositoryManagement/String…
dhoehna Sep 24, 2024
c9a67f5
Update tools/RepositoryManagement/DevHome.RepositoryManagement/String…
dhoehna Sep 24, 2024
0e2b21a
Update tools/RepositoryManagement/DevHome.RepositoryManagement/String…
dhoehna Sep 24, 2024
5400dd0
Adressing comments
dhoehna Sep 24, 2024
f90a5c8
Merge branch 'user/dhoehna/DatabaseMigrationsAndTodos' of https://git…
dhoehna Sep 24, 2024
5a8051b
Adressing comments
dhoehna Sep 25, 2024
41a8d4e
Addressing code quality comments
dhoehna Sep 27, 2024
856e0f0
Update database/DevHome.Database/DatabaseModels/RepositoryManagement/…
dhoehna Sep 28, 2024
1dbed3a
Fixing some issues.
dhoehna Sep 28, 2024
fed4755
Added a TODO
dhoehna Sep 28, 2024
fa22fce
Adding drop down to select a source control provider
dhoehna Sep 30, 2024
20a433e
Hide source control selection
dhoehna Oct 1, 2024
85c0014
FIxing indentation
dhoehna Oct 1, 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
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 DevHomeDatabaseContextEvent : 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 DevHomeDatabaseContextEvent(string step)
{
Step = step;
}

public DevHomeDatabaseContextEvent(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.
}
}
38 changes: 38 additions & 0 deletions common/TelemetryEvents/DevHomeDatabase/DevHomeDatabaseEvent.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 DevHomeDatabaseEvent : 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 DevHomeDatabaseEvent(string step)
{
Step = step;
}

public DevHomeDatabaseEvent(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,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 EnhanceRepositoryErrorEvent : 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 EnhanceRepositoryErrorEvent(string action, int hresult, string errorMessage, string repositoryName)
{
Action = action;
Hresult = hresult;
ErrorMessage = errorMessage;
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 @@ -30,6 +30,10 @@ public class Repository
// This causes any fluent API statements to get ignored.
public string? RepositoryUri { get; set; }

public Guid? SourceControlClassId { get; set; }

public bool HasAssignedSourceControlProvider => SourceControlClassId == null ? false : SourceControlClassId.Value != Guid.Empty;

public DateTime? CreatedUTCDate { get; set; }

public DateTime? UpdatedUTCDate { get; set; }
Expand Down
1 change: 1 addition & 0 deletions database/DevHome.Database/DevHomeDatabaseContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
repositoryEntity.Property(x => x.CreatedUTCDate).HasDefaultValueSql("datetime()");
repositoryEntity.Property(x => x.UpdatedUTCDate).HasDefaultValueSql("datetime()");
repositoryEntity.Property(x => x.RepositoryUri).HasDefaultValue(string.Empty);
repositoryEntity.Property(x => x.SourceControlClassId).HasDefaultValue(Guid.Empty);
repositoryEntity.ToTable("Repository");
}
}
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 @@ -27,6 +27,7 @@ protected override void Up(MigrationBuilder migrationBuilder)
IsHidden = table.Column<bool>(type: "INTEGER", nullable: false),
ConfigurationFileLocation = table.Column<string>(type: "TEXT", nullable: true, defaultValue: string.Empty),
RepositoryUri = table.Column<string>(type: "TEXT", nullable: true, defaultValue: string.Empty),
SourceControlClassId = table.Column<Guid>(type: "TEXT", nullable: true, defaultValue: Guid.Empty),
CreatedUTCDate = table.Column<DateTime>(type: "TEXT", nullable: true, defaultValueSql: "datetime()"),
UpdatedUTCDate = table.Column<DateTime>(type: "TEXT", nullable: true, defaultValueSql: "datetime()"),
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ protected override void BuildModel(ModelBuilder modelBuilder)
.HasColumnType("TEXT")
.HasDefaultValue(string.Empty);

b.Property<Guid?>("SourceControlClassId")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT")
.HasDefaultValue(Guid.Empty);

b.Property<DateTime?>("UpdatedUTCDate")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ public class RepositoryManagementDataAccessService

private readonly DevHomeDatabaseContextFactory _databaseContextFactory;

public RepositoryManagementDataAccessService(DevHomeDatabaseContextFactory databaseContextFactory)
public RepositoryManagementDataAccessService(
DevHomeDatabaseContextFactory databaseContextFactory)
{
_databaseContextFactory = databaseContextFactory;
}
Expand All @@ -30,20 +31,23 @@ public RepositoryManagementDataAccessService(DevHomeDatabaseContextFactory datab
/// Makes a new Repository entity with the provided name and location then saves it
/// to the database.
/// </summary>
/// <param name="repositoryName">The name of the repository to add.</param>
/// <param name="cloneLocation">The local location the repository is cloned to.</param>
/// <returns>The new repository. Can return null if the database threw an exception.</returns>
public Repository? MakeRepository(string repositoryName, string cloneLocation, Uri repositoryUri)
public Repository MakeRepository(string repositoryName, string cloneLocation, string repositoryUri)
{
return MakeRepository(repositoryName, cloneLocation, string.Empty, repositoryUri);
}

public Repository? MakeRepository(string repositoryName, string cloneLocation, string configurationFileLocationAndName, Uri repositoryUri)
public Repository MakeRepository(string repositoryName, string cloneLocation, string configurationFileLocationAndName, string repositoryUri)
{
return MakeRepository(repositoryName, cloneLocation, configurationFileLocationAndName, repositoryUri, Guid.Empty);
}

public Repository MakeRepository(string repositoryName, string cloneLocation, string configurationFileLocationAndName, string repositoryUri, Guid sourceControlProviderClassId)
{
var existingRepository = GetRepository(repositoryName, cloneLocation);
if (existingRepository != null)
{
_log.Warning($"A Repository with name {repositoryName} and clone location {cloneLocation} exists in the repository already.");
_log.Information($"A Repository with name {repositoryName} and clone location {cloneLocation} exists in the repository already.");
return existingRepository;
}

Expand All @@ -52,6 +56,7 @@ public RepositoryManagementDataAccessService(DevHomeDatabaseContextFactory datab
RepositoryName = repositoryName,
RepositoryClonePath = cloneLocation,
RepositoryUri = repositoryUri.ToString(),
SourceControlClassId = sourceControlProviderClassId,
};

if (!string.IsNullOrEmpty(configurationFileLocationAndName))
Expand All @@ -78,7 +83,7 @@ public RepositoryManagementDataAccessService(DevHomeDatabaseContextFactory datab
TelemetryFactory.Get<ITelemetry>().Log(
"DevHome_Database_Event",
LogLevel.Critical,
new DatabaseEvent(nameof(MakeRepository), ex));
new DevHomeDatabaseEvent(nameof(MakeRepository), ex));
return new Repository();
}

Expand Down Expand Up @@ -142,8 +147,6 @@ public bool UpdateCloneLocation(Repository repository, string newLocation)
return false;
}

// TODO: Figure out a method to update the entity in the database and
// the entity in memory.
// Maybe update the tracking information on repository. This way
// EF will catch the change.
repository.RepositoryClonePath = newLocation;
Expand Down Expand Up @@ -173,6 +176,38 @@ public bool UpdateCloneLocation(Repository repository, string newLocation)
return true;
}

public bool SetSourceControlId(Repository repository, Guid sourceControlId)
{
try
{
using var dbContext = _databaseContextFactory.GetNewContext();
var repositoryToUpdate = dbContext.Repositories.Find(repository.RepositoryId);
if (repositoryToUpdate == null)
{
_log.Warning($"{nameof(UpdateCloneLocation)} was called with a RepositoryId of {repository.RepositoryId} and it does not exist in the database.");
return false;
}

// TODO: Figure out a method to update the entity in the database and
// the entity in memory.
repository.SourceControlClassId = sourceControlId;
repositoryToUpdate.SourceControlClassId = sourceControlId;

dbContext.SaveChanges();
}
catch (Exception ex)
{
_log.Error(ex, "Exception when updating the clone location.");
TelemetryFactory.Get<ITelemetry>().Log(
"DevHome_Database_Event",
LogLevel.Critical,
new DatabaseEvent(nameof(UpdateCloneLocation), ex));
return false;
}

return true;
}

public void SetIsHidden(Repository repository, bool isHidden)
{
try
Expand Down Expand Up @@ -214,7 +249,6 @@ public void RemoveRepository(Repository repository)
}

dbContext.Repositories.Remove(repositoryToRemove);

dbContext.SaveChanges();
}
catch (Exception ex)
Expand Down
3 changes: 0 additions & 3 deletions src/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,6 @@ public App()
}).
ConfigureServices((context, services) =>
{
// Add databse connection
services.AddDatabase(context);
Copy link
Contributor

Choose a reason for hiding this comment

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

Was this a duplicate from somewhere else?


// Add Serilog logging for ILogger.
services.AddLogging(lb => lb.AddSerilog(dispose: true));

Expand Down
29 changes: 26 additions & 3 deletions test/Database/RepositoryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,16 @@ namespace DevHome.Test.Database;
[TestClass]
public class RepositoryTests
{
private const string ConfigurationFileLocation = @"The\Best\Configuration\Location";

private const string CloneLocation = @"The\Best\File\Location";
private const string CloneLocation = @"TestSource\repos";

private const string RepositoryName = "DevHome";

private const string ConfigurationFileLocation = @".configurations\configuration.dsc.yaml";

private const string RepositoryUri = "https://www.github.com/microsoft/devhome";

private readonly string _repositoryCloneLocation = Path.Join(CloneLocation, RepositoryName);

[TestInitialize]
public void ResetDatabase()
{
Expand All @@ -33,6 +35,26 @@ public void ResetDatabase()

dbContext.Database.EnsureDeleted();
dbContext.Database.EnsureCreated();

if (Directory.Exists(_repositoryCloneLocation))
{
// Cumbersome, but needed to remove read-only files.
foreach (var repositoryFile in Directory.EnumerateFiles(_repositoryCloneLocation, "*", SearchOption.AllDirectories))
{
File.SetAttributes(repositoryFile, FileAttributes.Normal);
File.Delete(repositoryFile);
}

foreach (var repositoryDirectory in Directory.GetDirectories(_repositoryCloneLocation, "*", SearchOption.AllDirectories).Reverse())
{
Directory.Delete(repositoryDirectory);
Copy link
Contributor

Choose a reason for hiding this comment

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

This might benefit from a "Try-catch" since the deletion of each file/folder might fail, and shouldn't fail the reset() and should proceed to the next item. Maybe log failure and proceed is best, since any dependent tests will indicate if it's a problem.

}

File.SetAttributes(_repositoryCloneLocation, FileAttributes.Normal);
Directory.Delete(_repositoryCloneLocation, false);
}

LibGit2Sharp.Repository.Clone(RepositoryUri, _repositoryCloneLocation);
}

[TestMethod]
Expand Down Expand Up @@ -86,5 +108,6 @@ public void MakefilledInRepository()
Assert.IsTrue(savedRepository.IsHidden);
Assert.IsTrue(savedRepository.HasAConfigurationFile);
Assert.AreEqual(RepositoryUri, savedRepository.RepositoryUri);
Assert.IsTrue(savedRepository.HasAConfigurationFile);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -156,14 +156,14 @@ public bool ShowRepositoryStatus
}

[RelayCommand]
public async Task AddFolderClick()
public async Task<string> AddFolderClick()
{
StorageFolder? repoRootFolder = null;
if (IsFeatureEnabled)
{
await Task.Run(async () =>
{
using var folderDialog = new WindowOpenFolderDialog();
StorageFolder? repoRootFolder = null;

try
{
Expand All @@ -186,6 +186,14 @@ await Task.Run(async () =>
});
RefreshTrackedRepositories();
}

return repoRootFolder == null ? string.Empty : repoRootFolder.Path;
}

public void AddRepositoryAlreadyOnMachine(string path)
{
RepoTracker.AddRepositoryPath(_unassigned, path);
RefreshTrackedRepositories();
}

public void RemoveTrackedRepositoryFromDevHome(string rootPath)
Expand Down
Loading