Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.

Conversation

@jcansdale
Copy link
Collaborator

@jcansdale jcansdale commented Oct 23, 2018

This is the first iteration of refactoring LocalRepositoryModel and GitService (see #2007).

I've focused on moving the code to where is should be, with as few functional changes as possible. There is more to do, but I think this makes sense as a chunk.

  • Replace ILocalRepositoryModel.CurrentBranch property with IGitService.CreateCurrentBranchModel(model) method
  • Move construction of LocalRepositoryModel to GitService.CreateLocalRepositoryModel
  • Move LocalRepositoryModel.GenerateUrl to LinkCommandBase
  • Move LocalReposotoryModel.Refresh to GitService.RefreshCloneUrl (this will be removed in Remove repository responsibilities from TeamExplorerServiceHolder (repository refactor part 2) #2025)
  • Get rid of LocalRepositoryModelFactory (we can use GitService instead)
  • Remove unused LocalRepositoryModel.HeadSha property

The most significant functional change was to replace the LocalRepositoryModel.CurrentBranch property with a GitService.CreateCurrentBranchModel(repositoryModel) method.

This was necessary because the IGitExt.ActiveRepositories property changed event fires before the current branch is actually changed. If we populate LocalRepositoryModel.CurrentBranch when the model is created, CurrentBranch ends up with information about the previous branch.

By deferring creation of the current branch model, we can populate it when the branch has actually changed and only create the branch model when it's actually required (the property change event can fire a lot).

Bugs to fix

Still to do

Now the junk has been removed from LocalReposotoryModel, we can decide how we want the models to look!

@codecov
Copy link

codecov bot commented Oct 23, 2018

Codecov Report

Merging #2008 into master will decrease coverage by 1.3%.
The diff coverage is 52.63%.

@@            Coverage Diff             @@
##           master    #2008      +/-   ##
==========================================
- Coverage   40.67%   39.36%   -1.31%     
==========================================
  Files         377      410      +33     
  Lines       16333    17572    +1239     
  Branches     2253     2422     +169     
==========================================
+ Hits         6643     6918     +275     
- Misses       9150    10117     +967     
+ Partials      540      537       -3
Impacted Files Coverage Δ
src/GitHub.Exports/Models/BranchModel.cs 35.71% <0%> (ø) ⬆️
...rc/GitHub.VisualStudio/Commands/OpenLinkCommand.cs 0% <0%> (ø)
...rc/GitHub.VisualStudio/Commands/CopyLinkCommand.cs 0% <0%> (ø)
...c/GitHub.VisualStudio/Commands/BlameLinkCommand.cs 0% <0%> (ø)
src/GitHub.App/Services/PullRequestService.cs 35.29% <0%> (ø) ⬆️
...eamFoundation.14/Base/TeamExplorerServiceHolder.cs 0% <0%> (ø) ⬆️
src/GitHub.TeamFoundation.14/RegistryHelper.cs 0% <0%> (ø) ⬆️
...ndation.14/Services/LocalRepositoryModelFactory.cs 0% <0%> (ø) ⬆️
...wModels/GitHubPane/PullRequestCreationViewModel.cs 97.35% <100%> (+0.03%) ⬆️
...nlineReviews/Services/PullRequestSessionManager.cs 83.75% <100%> (ø) ⬆️
... and 42 more

Move LocalRepositoryModel construction tests to new home.
This property wasn't being used.
We Now only need the CreateLocalRepositoryModel(localPath) overload.
Previously the current branch was being read when CurrentBranch was
fetched. This changes it to be read when the LocalRepositoryModel is
created.
Remove redundant code and usings.
@jcansdale jcansdale changed the title [wip] Refactor repository models Refactor repository models (part 1) Oct 24, 2018
@jcansdale jcansdale changed the title Refactor repository models (part 1) [wip] Refactor repository models (part 1) Oct 24, 2018
@jcansdale
Copy link
Collaborator Author

I think updating the Checkout ... link state might have broken with this PR. Need to investigate....

image

/// <summary>
/// Gets the repository clone URL.
/// </summary>
public UriString CloneUrl
Copy link
Contributor

Choose a reason for hiding this comment

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

Future: should these properties be raising change notifications? If so, should other properties also be raising them (CurrentBranch for example).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think we should aim to get rid of the Refresh command so this model would be immutable after creation.

/// <summary>
/// Gets an icon for the repository that displays its private and fork state.
/// </summary>
public Octicon Icon
Copy link
Contributor

Choose a reason for hiding this comment

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

Future: move this out of the model: it's a view model-level reponsibility that only really applies to the repository list in Team Explorer.

{
var repo = ServiceProvider.TryGetService<IGitService>().GetRepository(path);
return new LocalRepositoryModel(repo.Info.WorkingDirectory.TrimEnd('\\'), GitService.GitServiceHelper);
return GitService.GitServiceHelper.CreateLocalRepositoryModel(repo.Info.WorkingDirectory.TrimEnd('\\'));
Copy link
Contributor

Choose a reason for hiding this comment

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

Is TrimEnd needed here? If so, should that logic be put into CreateLocalRepositoryModel?

Previously CurrentBranch was created as the property was read. We now
need a way to refresh it.
Copy link
Collaborator Author

@jcansdale jcansdale left a comment

Choose a reason for hiding this comment

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

Should this logic be part of RepositoryViewModel?

Copy link
Collaborator Author

@jcansdale jcansdale left a comment

Choose a reason for hiding this comment

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

Should this logic be part of RepositoryViewModel?

Copy link
Collaborator Author

@jcansdale jcansdale left a comment

Choose a reason for hiding this comment

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

Should this logic be part of RepositoryViewModel?

It appears VSGitExt.ActiveRepositoriesChanged is fired before the local
repository has actually changed its branch. This means we can't read
the branch information immediately!
Copy link
Collaborator Author

@jcansdale jcansdale left a comment

Choose a reason for hiding this comment

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

Comments about removing CurrentBranch.

Name = name,
Icon = Octicon.repo
};

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is currently being refreshed before the branch has actually changed. :-(

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

There is now a CreateCurrentBranchModel command instead of the CurrentBranch property. We'll still need to be careful about calling it too soon.

Remove the ILocalRepositoryModel.CurrentBranch property and explicitly
call IGitService.CreateCurrentBranchModel instead.
Fix all the broken tests.
Convert GetPullRequestForCurrentBranch to return (string owner, int
number). This allows the tuple to be compared directly.
We can now use GitService as a LocalRepositoryMode factory.
@jcansdale jcansdale force-pushed the fixes/2007-refactor-repository-models branch from 3abf4d6 to db41ef9 Compare October 31, 2018 17:30
@jcansdale jcansdale changed the title [wip] Refactor repository models (part 1) Refactor repository models (part 1) Nov 1, 2018
@jcansdale jcansdale changed the title Refactor repository models (part 1) Refactor repository models (repository refactor part 1) Nov 1, 2018
Copy link
Contributor

@grokys grokys left a comment

Choose a reason for hiding this comment

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

LGTM! a couple of nits and questions but going to approve anyway.

/// Creates a new branch model for the current branch.
/// </summary>
/// <param name="model">The <see cref="ILocalRepositoryModel" /> to create a current branch model for.</param>
/// <returns>A new branch model.</returns>
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this might be less verbose if it were simply called GetBranch: I'd tend to think of it more as a method to get the state of an ILocalRepositoryModel than a factory method. What do you think?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We could change it to GetBranch(string name = "HEAD"). Do you think that would make sense? Otherwise we'd probably need to qualify it with GetHeadBranch or something?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah I think that would make sense.

else if (newRepositoryPath != null)
{
log.Debug("Fire StatusChanged event when PullRequest changes for ActiveRepository");
log.Debug("Fire StatusChanged event when on a repository and anything changes");
Copy link
Contributor

Choose a reason for hiding this comment

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

Reads a bit yoda-y ;)

Copy link
Collaborator Author

@jcansdale jcansdale Nov 2, 2018

Choose a reason for hiding this comment

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

I'm not sure if that's a feature? 😉

I'll change it to:
"Fire StatusChanged event if anything about an active repository has changed"

log.Debug("Fire StatusChanged event when BranchName changes for ActiveRepository");
StatusChanged?.Invoke(this, EventArgs.Empty);
}
else if (newHeadSha != headSha)
Copy link
Contributor

Choose a reason for hiding this comment

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

So StatusChanged is no longer firing when HEAD changes? Is this because it wasn't working before anyway? (i.e. it was firing before the actual change)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Now either a repository change event will be fired when we set ActiveRepository or a StatusChanged will be fired if we think anything about the active repository might have changed (including when the HEAD changed).

This is actually similar to what was happening before because newPullRequest != pullRequest was always returning true (the tuple comparison issue).

I have changed it so that if we're not on a repository, no StatusChanged event will fire.

@jcansdale
Copy link
Collaborator Author

Merged as part of #2028.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants