-
Notifications
You must be signed in to change notification settings - Fork 340
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
Implement Add Repositories UI in the File Explorer Dev Home Page #3488
Implement Add Repositories UI in the File Explorer Dev Home Page #3488
Conversation
tools/Customization/DevHome.FileExplorerSourceControlIntegration/Services/RepositoryTracking.cs
Outdated
Show resolved
Hide resolved
tools/Customization/DevHome.FileExplorerSourceControlIntegration/Services/RepositoryTracking.cs
Show resolved
Hide resolved
tools/Customization/DevHome.Customization/ViewModels/FileExplorerViewModel.cs
Outdated
Show resolved
Hide resolved
tools/Customization/DevHome.Customization/Views/AddRepositoriesView.xaml
Outdated
Show resolved
Hide resolved
tools/Customization/DevHome.Customization/Strings/en-us/Resources.resw
Outdated
Show resolved
Hide resolved
tools/Customization/DevHome.Customization/ViewModels/FileExplorerViewModel.cs
Outdated
Show resolved
Hide resolved
tools/Customization/DevHome.Customization/ViewModels/FileExplorerViewModel.cs
Outdated
Show resolved
Hide resolved
tools/Customization/DevHome.Customization/ViewModels/FileExplorerViewModel.cs
Outdated
Show resolved
Hide resolved
tools/Customization/DevHome.Customization/Views/AddRepositoriesView.xaml
Outdated
Show resolved
Hide resolved
tools/Customization/DevHome.Customization/Views/AddRepositoriesView.xaml.cs
Outdated
Show resolved
Hide resolved
tools/Customization/DevHome.Customization/Views/AddRepositoriesView.xaml.cs
Outdated
Show resolved
Hide resolved
tools/Customization/DevHome.Customization/Views/FileExplorerPage.xaml
Outdated
Show resolved
Hide resolved
tools/Customization/DevHome.Customization/Views/FileExplorerPage.xaml
Outdated
Show resolved
Hide resolved
tools/Customization/DevHome.Customization/Views/AddRepositoriesView.xaml
Outdated
Show resolved
Hide resolved
tools/Customization/DevHome.Customization/Views/AddRepositoriesView.xaml
Outdated
Show resolved
Hide resolved
<DropDownButton.Flyout> | ||
<MenuFlyout | ||
Placement="Bottom"> | ||
<!-- WinUI does not currently allow populating MenuFlyoutItems dynamically within a DataTemplate. --> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please file an issue/bug to track this. We only have the one provider at the moment, so this shouldn't block some testing/selfhosting. But let's not forget to come back to this and fix it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding this as a potential fix. Using an MSBuild task to iterate through all the extensions and populate XAML before it is built. It would be difficult though. Just an idea.
16b9823
to
e7bc4e1
Compare
This reverts commit f30055f.
**Summary of the pull request** This PR contains implementation changes for the File Explorer Source Control Integration experimental feature. This feature will allow File Explorer to obtain property information from source control technologies for display (image attached below): **Detailed description of the pull request / Additional comments** This PR contains the following changes: - Reference official Dev Home SDK version (that defines APIs for File Explorer Source Control Integration) - Declare FileExplorerSourceControlIntegration as an experimental feature - The FileExplorerSourceControlIntegration project which creates a COM Server used to communicate information with File Explorer - The FileExplorerGitIntegration project which allows Dev Home to come with an inbox extension that understands git - Basic Unit Tests **Validation steps performed** SDK and MSIX local builds Tested Git Integration File Explorer behavior inside VM Related work items: #48431506
* declare appextension for git, find all source control extensions, UI changes, SDK changes, get extension information to use for mapping * changes to map extension to registered root paths, add validation to git implementation * changes after testing * use serilog in validation code * reorder using * use published SDK version * address PR feedback * address PR feedback * address PR feedback * Minor cleanup of RepositoryTracking.cs --------- Co-authored-by: Ryan Shepherd <ryansh@microsoft.com>
extensions/GitExtension/FileExplorerGitIntegration/GitLocalRepositoryProviderFactory`1.cs
Outdated
Show resolved
Hide resolved
latestCommit = FindLatestCommit(relativePath, repository); | ||
if (latestCommit != null) | ||
{ | ||
result.Add("System.VersionControl.LastChangeMessage", latestCommit.MessageShort); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PropName can be used here instead of re-typing the string.
return result; | ||
} | ||
|
||
foreach (var propName in properties) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe the null checks are used because of iterating through the properties and this needs the latest commit to be not null.
I don't like the duplication of the check.
If LatestCommit
returns null for a property, would a second call to LatestCommit
return a non-null value? If this is the case the call to LatestCommit
can be moved outside the foreach loop.
The null check for LatestCommit
still needs to be in each case "If not null, add the property"
{ | ||
switch (propName) | ||
{ | ||
case "System.VersionControl.LastChangeMessage": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another way to do this is,
- Put
LatestCommit
outside of the for loop. - For every property use result.Add(propName, latestCommit?.[PropertyName] ?? string.empty)
- Before returning result remove all entries that contain string.empty.
var commits = repository.Commits; | ||
|
||
// Check the most recent commit and bail if the file is not present | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this in its own scope?
// Check the most recent commit and bail if the file is not present | ||
{ | ||
var firstCommit = commits.FirstOrDefault(); | ||
if (firstCommit != null && firstCommit.Tree[relativePath] == null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this can be simplified to commits.FirstOrDefault()?.Tree?[relativePath] == null
} | ||
} | ||
|
||
foreach (var currentCommit in commits) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIT: commit.Select(x => x.Tree[relativePath]).Where(x +> x is not null)
|
||
var parents = currentCommit.Parents; | ||
var count = parents.Count(); | ||
if (count == 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIT: currentCommit.Parents.Count() == 0
catch (Exception ex) | ||
{ | ||
log.Error("RepositoryCache", "Failed to create Repository", ex); | ||
if (repo != null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIT: repo?.Dispose()
public static void Main([System.Runtime.InteropServices.WindowsRuntime.ReadOnlyArray] string[] args) | ||
{ | ||
// Set up Logging | ||
Environment.SetEnvironmentVariable("DEVHOME_LOGS_ROOT", Path.Join(DevHome.Common.Logging.LogFolderRoot, "FileExplorerGitIntegration")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIT: You can use Microsoft.Windows.System.EnvironmentManager and the EV will be removed when the app is uninstalled.
return new SourceControlValidationResult(ResultType.Failure, ErrorType.RepositoryProvderCreationFailed, null, null, null); | ||
} | ||
|
||
ILocalRepositoryProvider provider = MarshalInterface<ILocalRepositoryProvider>.FromAbi(providerPtr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why use PInvoke to get the ILocalRepositoryProvider? I believe DevHome has interfaces to get the providers already.
{ | ||
lock (trackRepoLock) | ||
{ | ||
var caseSensitiveDictionary = fileService.Read<Dictionary<string, string>>(RepoStoreOptions.RepoStoreFolderPath, RepoStoreOptions.RepoStoreFileName); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
old name? Can the name be changed to something more descriptive?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Considering on line 72 the case is ignored.
{ | ||
if (!TrackedRepositories.ContainsKey(rootPath)) | ||
{ | ||
TrackedRepositories[rootPath] = extensionCLSID!; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand. Tracked repositories is a map from a root path to the extension that is tracking the repository. I understand now. Okay.
NIT: change the name to TrackedRepositoriesToExtension, or something similar.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is why so many other files use pUnk to determing the extension type.
if (TrackedRepositories.TryGetValue(rootPath, out var value)) | ||
{ | ||
log.Information("Source Control Provider returned for root path"); | ||
return TrackedRepositories[rootPath]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return value.
@@ -0,0 +1,180 @@ | |||
// Copyright (c) Microsoft Corporation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIT for the file: Make CLSID the second argument. That is what it is. All other methods need either
- nothing
- RootPath
- RootPath and CLSID.
This keeps the arguments in a consistent order.
@dhoehna Just a heads up. This PR contains alot of changes which have already been merged to the feature branch. Since the feature branch was rebased to latest in main, the changes are appearing here. I am currently (locally) fixing the state of the branch. As such, the PR will only contain the UI changes. However, we do plan to create a PR for review to commit to main soon. Thanks! |
{ | ||
if (TrackedRepositories.TryGetValue(rootPath, out var existingExtensionCLSID)) | ||
{ | ||
TrackedRepositories[rootPath] = extensionCLSID; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you already retrieved TrackedRepositories[rootPath] in TryGetValue. existingExtensionCLSID
can be used in this scope.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NVM. This is used to check the existence of the key. In the case. can you use .ContainsKey instead?
TrackedRepositories = caseSensitiveDictionary.ToDictionary(entry => entry.Key, entry => entry.Value, StringComparer.OrdinalIgnoreCase); | ||
} | ||
|
||
LastRestore = DateTime.Now; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIT: use UTcNow. An edge case can occur if using .Now. For example, Daylight savings time occurred. Or the user moved between times zones.
|
||
internal ILocalRepositoryProvider GetLocalProvider(string rootPath) | ||
{ | ||
// TODO: Iterate extensions to find the correct one for this rootPath. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this TODO still relevant?
{ | ||
TrackedRepositories.Clear(); | ||
var repoCollection = RepoTracker.GetAllTrackedRepositories(); | ||
foreach (KeyValuePair<string, string> data in repoCollection) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIT: repoCollection.Select(x => new RepositoryInformation(x.Key, x.Value))
|
||
IDictionary<string, object> IExtraFolderPropertiesHandler.GetProperties(string[] propertyStrings, string rootFolderPath, string relativePath) | ||
{ | ||
var localProvider = GetLocalProvider(rootFolderPath); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIT: GetLocalProvider(rootFolderPath).GetRepository(rootFolderPath)
} | ||
|
||
// TODO: How to detect between WinRT/IInspectable and COM/IUnknown interfaces | ||
ppvObject = MarshalInspectable<T>.CreateMarshaler2(_createSourceControlProvider(), riid, true).Detach(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this TODO still relevant?
2ea72d7
to
3ae6b69
Compare
136ea6e
into
feature/fileexplorer-sourcecontrol-integration
Summary of the pull request
This PR removes the temporary UI and implements the design based UI for adding and removing repositories (for source control integration) in the File Explorer Settings page.
References and relevant issues
Detailed description of the pull request / Additional comments
Validation steps performed
Built msix release pckg
Validated UI functionality
PR checklist