Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign upGitHub is where the world builds software
Millions of developers and companies build, ship, and maintain their software on GitHub — the largest and most advanced development platform in the world.
Add list of repos to the connect page #32
Conversation
Adds a list view showing the list of repositories that VS knows about and that are associated with the github connection (i.e., the remote url corresponds to the github connection section information)
Conflicts: src/GitHub.Exports/Primitives/UriString.cs src/GitHub.Exports/Services/Services.cs src/GitHub.VisualStudio/Base/TeamExplorerItemBase.cs
The repository list is loaded from the registry into ConnectionManager. Don't save it in the cache for now, so it doesn't break compatibility with the existing cache files and we don't really need to cache it right now. Let's see how it works just loading directly from the registry for now.
Offering to open a solution or project is the only way to switch the context to the new repo. Since it's likely that that's what the user wants to do anyway (why clone a repo otherwise), let's do that.
|
Fixes #16 |
|
Since I'm already hooking up into a property change that tells me the cloning is done, we can also do it for the repo creation and maybe switch out the message. Could be a nice thing to have. |
|
I haven't added tests for the new classes yet, doing that tomorrow, probably on a separate branch off of this one. /cc @haacked |
|
Should I order the repo list? |
Shouldn't we do the same thing that double clicking a repository listed in the "Local Git Repositories" section?
Yeah, I think so. |
I wish, but there's no API to trigger that at all. It's switching the source control context (closing opened solutions and changing to another repo) without actually opening anything in the new repo. It's all private logic that we have no access to. TBH, I think offering to open a solution in the selected repo when you double click is better than blindly closing the current one and switching to the selected repo without doing anything else or asking the user. It's a very confusing experience, you don't know what happened and VS enters into this limbo state where nothing is loaded but there's some sort of source control context that's active, which changes all the default paths for things (and you only notice if you pay particular attention to the default path in the project creation dialog). The fact that it closes the currently opened solution without asking annoys me particularly, I don't like things happening without warning, but that's just me |
|
|
The previous logic wouldn't work if there is no active repo in VS
| [AllowNull] | ||
| public ISimpleRepositoryModel SelectedRepository { | ||
| [return: AllowNull] get { return selectedRepository; } | ||
| set { selectedRepository = value; this.RaisePropertyChange(); } } |
haacked
Aug 27, 2015
Contributor
Nitpick Neymar: brace formatting here is inconsistent with the rest of the code. 😄
Nitpick Neymar: brace formatting here is inconsistent with the rest of the code.
| @@ -129,23 +182,70 @@ void UpdateConnection() | |||
| void OnPropertyChange(object sender, System.ComponentModel.PropertyChangedEventArgs e) | |||
haacked
Aug 27, 2015
Contributor
You could probably omit the System.CompenentModel. part here since it's already declared in the usings section.
You could probably omit the System.CompenentModel. part here since it's already declared in the usings section.
| SelectedRepository = r; | ||
| var repo = await ApiFactory.Create(r.CloneUrl).GetRepository(); | ||
| r.SetIcon(repo.Private, repo.Fork); | ||
| }).ToList(); |
haacked
Aug 27, 2015
Contributor
The use of ToList here is confusing because we're not using the return value.
I think ForEach would more clearly express the intent here.
e.NewItems
.Cast<ISimpleRepositoryModel>()
.ForEach(async r =>
{
if (String.Equals(Holder.ActiveRepo?.RepositoryPath, r.LocalPath, StringComparison.CurrentCultureIgnoreCase))
SelectedRepository = r;
var repo = await ApiFactory.Create(r.CloneUrl).GetRepository();
r.SetIcon(repo.Private, repo.Fork);
});
The use of ToList here is confusing because we're not using the return value.
I think ForEach would more clearly express the intent here.
e.NewItems
.Cast<ISimpleRepositoryModel>()
.ForEach(async r =>
{
if (String.Equals(Holder.ActiveRepo?.RepositoryPath, r.LocalPath, StringComparison.CurrentCultureIgnoreCase))
SelectedRepository = r;
var repo = await ApiFactory.Create(r.CloneUrl).GetRepository();
r.SetIcon(repo.Private, repo.Fork);
});
shana
Aug 27, 2015
Author
Collaborator
Yup, ForEach is better! 👍
Yup, ForEach is better!
| var old = Repositories.FirstOrDefault(x => String.Equals(Holder.ActiveRepo?.RepositoryPath, x.LocalPath, StringComparison.CurrentCultureIgnoreCase)); | ||
| // open the solution selection dialog when the user wants to switch to a different repo | ||
| // since there's no other way of changing the source control context in VS | ||
| if (SelectedRepository != old) |
haacked
Aug 27, 2015
Contributor
I haven't thought this through, but this is a reference equality check. Should this be:
if (!Equals(SelectedRepository, old))
I haven't thought this through, but this is a reference equality check. Should this be:
if (!Equals(SelectedRepository, old))
shana
Aug 27, 2015
Author
Collaborator
It's on purpose, the equality operators are overriden in SimpleRepositoryModel to perform comparisons based on content (because the instances are different, maybe not their content). There's comments in SimpleRepositoryModel to that effect.
It's on purpose, the equality operators are overriden in SimpleRepositoryModel to perform comparisons based on content (because the instances are different, maybe not their content). There's comments in SimpleRepositoryModel to that effect.
shana
Aug 28, 2015
Author
Collaborator
nvm, I took the overloaded operators out and switched to Equals on this
nvm, I took the overloaded operators out and switched to Equals on this
| { | ||
| if (values[0] is ISimpleRepositoryModel) | ||
| return ((ISimpleRepositoryModel)values[0]).Name; | ||
| return String.Empty; |
haacked
Aug 27, 2015
Contributor
This is probably more a code style issue than an actual perf issue since array access and casting types is pretty cheap, but I would probably write the above as:
It probably doesn't matter for perf, but I tend to replace double cast checks with something like:
var model = values[0] as ISimpleRepositoryModel;
return model != null ? model.Name : String.Empty;
That accesses the array only once and type checks only once. However, more importantly to me, I think that's a bit more readable.
This is probably more a code style issue than an actual perf issue since array access and casting types is pretty cheap, but I would probably write the above as:
It probably doesn't matter for perf, but I tend to replace double cast checks with something like:
var model = values[0] as ISimpleRepositoryModel;
return model != null ? model.Name : String.Empty;That accesses the array only once and type checks only once. However, more importantly to me, I think that's a bit more readable.
haacked
Aug 27, 2015
Contributor
Or even better.
var model = values[0] as ISimpleRepositoryModel;
return model?.Name ?? String.Empty;
Or even better.
var model = values[0] as ISimpleRepositoryModel;
return model?.Name ?? String.Empty;
Sorry, i don't think i was being clear. I think that popping up the New Project dialog after creating a new repository should be done in a separate PR too. I don't think it belongs in this PR which should solely be focused on listing repositories. |
Oh yeah, I'm taking that part out too |
When there's more than one connection, logging out of the first connection would cause it to render the logged out connection instead of the one still logged in.
Add a tracker class to accurately track the state of the local git repository list, so we can update our lists accordingly. Cleanup and fix a bunch of list-refreshing stuff.
Operator precedence is kinda important...
|
Ok, I think I caught all the issues and fixed all the things! |
| if (context == null) | ||
| return item?.Name ?? String.Empty; | ||
|
|
||
| if (context.SectionConnection.Username == item.CloneUrl.Owner) |
haacked
Sep 2, 2015
Contributor
If context not null, but item was null, we'd get a NullReferenceException here. Perhaps line 79 should be if (context == null || item == null)
If context not null, but item was null, we'd get a NullReferenceException here. Perhaps line 79 should be if (context == null || item == null)
| string old; | ||
| using (var key = Registry.CurrentUser.OpenSubKey(PathsKey, true)) | ||
| { | ||
| old = (string)key.GetValue("Value0", string.Empty, RegistryValueOptions.DoNotExpandEnvironmentNames); |
haacked
Sep 2, 2015
Contributor
Potential NullReferenceException here with key.
Potential NullReferenceException here with key.
| { | ||
| using (var subkey = key.OpenSubKey(x)) | ||
| { | ||
| var path = subkey.GetValue("Path") as string; |
haacked
Sep 2, 2015
Contributor
Potential NullReferenceException here. If we want to throw an exception when subkey is null (since the caller is handling it), we probably should throw something better and more informative than NullReferenceException.
Potential NullReferenceException here. If we want to throw an exception when subkey is null (since the caller is handling it), we probably should throw something better and more informative than NullReferenceException.
|
I went ahead and fixed the potential nullrefs. I think this branch is good. |
Add list of repos to the connect page




I'm not sure it's worth caching the known GitHub repositories list in our connection cache instead of just poking the registry every time the Connect page is loaded. I'll have to monitor the registry for changes so I can update our cache when new repos get added to VS (because there's no API to notify us of that)