Skip to content
This repository was archived by the owner on Dec 5, 2024. It is now read-only.

Commit 4cfcb06

Browse files
authored
Merge pull request #378 from github-for-unity/stanley/branches-view-fixes
Edits to the branches-view branch
2 parents 205da5b + 532621b commit 4cfcb06

File tree

90 files changed

+3009
-2050
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

90 files changed

+3009
-2050
lines changed

GitHub.Unity.sln.DotSettings

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@
342342
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAlwaysTreatStructAsNotReorderableMigration/@EntryIndexedValue">True</s:Boolean>
343343
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
344344
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean>
345+
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EUnitTestFramework_002ESettings_002EMigrations_002ERemoveBuildPolicyAlwaysMigration/@EntryIndexedValue">True</s:Boolean>
345346
<s:Boolean x:Key="/Default/Environment/UnitTesting/ShadowCopy/@EntryValue">False</s:Boolean>
346347
<s:String x:Key="/Default/Housekeeping/UnitTestingMru/UnitTestSessionDefault/PlatformType/@EntryValue">x64</s:String>
347348
</wpf:ResourceDictionary>

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ The GitHub for Unity extension brings [Git](https://git-scm.com/) and GitHub int
4747

4848
### Requirements
4949

50-
- Unity 5.4-5.6
51-
- We've only tested the extension so far on Unity 5.4 to 5.6. There's currently an blocker issue opened for 5.3 support, so we know it doesn't run there. There are some issues for 2017.x, so it may or may not run well on that version. Personal edition is fine.
50+
- Unity 5.4-2017.1
51+
- We've only tested the extension so far on Unity 5.4 to 2017.1. There's currently an blocker issue opened for 5.3 support, so we know it doesn't run there. There are some issues for 2017.2, so it may or may not run well on that version. Personal edition is fine.
5252
- Git and Git LFS 2.x
5353

5454
#### Git on macOS

common/properties.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
<UnityDir Condition="$(UnityDir) == '' and Exists('$(SolutionDir)\script\lib\UnityEditor.dll')">$(SolutionDir)\script\lib\</UnityDir>
99
<UnityDir Condition="$(UnityDir) == '' and Exists('$(SolutionDir)\lib\UnityEditor.dll')">$(SolutionDir)\lib\</UnityDir>
10+
<UnityDir Condition="$(UnityDir) == '' and Exists('C:\Program Files\Unity\Editor\Data\Managed\UnityEditor.dll')">C:\Program Files\Unity\Editor\Data\Managed\</UnityDir>
1011
<UnityDir Condition="$(UnityDir) == '' and Exists('C:\Program Files (x86)\Unity\Editor\Data\Managed\UnityEditor.dll')">C:\Program Files (x86)\Unity\Editor\Data\Managed\</UnityDir>
1112
<UnityDir Condition="$(UnityDir) == '' and Exists('\Applications\Unity\Unity.app\Contents\Managed\UnityEditor.dll')">\Applications\Unity\Unity.app\Contents\Managed\</UnityDir>
1213
<BuildConfig Condition=" '$(BuildConfig)' == '' ">Debug</BuildConfig>

docs/contributing/how-to-build.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ This repository is LFS-enabled. To clone it, you should use a git client that su
99
- Visual Studio 2015+ or Mono 4.x + bash shell (git bash).
1010
- Mono 5.x will not work
1111
- `UnityEngine.dll` and `UnityEditor.dll`.
12-
- If you've installed Unity in the default location of `C:\Program Files\Unity` or `C:\Program Files (x86)\Unity`, the build will be able to reference these DLLs automatically. Otherwise, you'll need to copy these DLLs from your Unity installation into the `lib` directory in order for the build to work
12+
- If you've installed Unity in the default location of `C:\Program Files\Unity` or `C:\Program Files (x86)\Unity`, the build will be able to reference these DLLs automatically. Otherwise, you'll need to copy these DLLs from `[Unity installation path]\Unity\Editor\Data\Managed` into the `lib` directory in order for the build to work
1313

1414
### MacOS
1515

1616
- Mono 4.x required.
1717
- Mono 5.x will not work
1818
- `UnityEngine.dll` and `UnityEditor.dll`.
19-
- If you've installed Unity in the default location of `/Applications/Unity`, the build will be able to reference these DLLs automatically. Otherwise, you'll need to copy these DLLs from your Unity installation into the `lib` directory in order for the build to work
19+
- If you've installed Unity in the default location of `/Applications/Unity`, the build will be able to reference these DLLs automatically. Otherwise, you'll need to copy these DLLs from `[Unity installation path]/Unity.app/Contents/Managed` into the `lib` directory in order for the build to work
2020

2121
## How to Build
2222

@@ -40,11 +40,11 @@ To be able to authenticate in GitHub for Unity, you'll need to:
4040
- [Register a new developer application](https://github.com/settings/developers) in your profile.
4141
- Copy [common/ApplicationInfo_Local.cs-example](../../common/ApplicationInfo_Local.cs-example) to `common/ApplicationInfo_Local.cs` and fill out the clientId/clientSecret fields for your application.
4242

43-
The build needs to reference `UnityEngine.dll` and `UnityEditor.dll`. These DLLs are included with Unity. If you've installed Unity in the default location, the build will be able to find them automatically. If not, copy these DLLs from your Unity installation into the `lib` directory in order for the build to work.
43+
The build needs to reference `UnityEngine.dll` and `UnityEditor.dll`. These DLLs are included with Unity. If you've installed Unity in the default location, the build will be able to find them automatically. If not, copy these DLLs from `[your Unity installation path]\Unity\Editor\Data\Managed` into the `lib` directory in order for the build to work.
4444

4545
### Visual Studio
4646

47-
To build with Visual Studio 2015 open the solution file `GitHub.Unity.sln`. Select `Build Solution` in the `Build` menu.
47+
To build with Visual Studio 2015+, open the solution file `GitHub.Unity.sln`. Select `Build Solution` in the `Build` menu.
4848

4949
### Mono and Bash (windows and mac)
5050

src/GitHub.Api/Application/ApiClient.cs

Lines changed: 104 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Linq;
4-
using System.Threading;
54
using System.Threading.Tasks;
65
using Octokit;
76

@@ -20,20 +19,13 @@ public static IApiClient Create(UriString repositoryUrl, IKeychain keychain)
2019
new GitHubClient(AppConfiguration.ProductHeader, credentialStore, hostAddress.ApiUri));
2120
}
2221

23-
private static readonly Unity.ILogging logger = Unity.Logging.GetLogger<ApiClient>();
22+
private static readonly ILogging logger = Logging.GetLogger<ApiClient>();
2423
public HostAddress HostAddress { get; }
2524
public UriString OriginalUrl { get; }
2625

2726
private readonly IKeychain keychain;
2827
private readonly IGitHubClient githubClient;
2928
private readonly ILoginManager loginManager;
30-
private static readonly SemaphoreSlim sem = new SemaphoreSlim(1);
31-
32-
IList<Organization> organizationsCache;
33-
Octokit.User userCache;
34-
35-
string owner;
36-
bool? isEnterprise;
3729

3830
public ApiClient(UriString hostUrl, IKeychain keychain, IGitHubClient githubClient)
3931
{
@@ -58,7 +50,7 @@ private async Task LogoutInternal(UriString host)
5850
await loginManager.Logout(host);
5951
}
6052

61-
public async Task CreateRepository(NewRepository newRepository, Action<Octokit.Repository, Exception> callback, string organization = null)
53+
public async Task CreateRepository(NewRepository newRepository, Action<GitHubRepository, Exception> callback, string organization = null)
6254
{
6355
Guard.ArgumentNotNull(callback, "callback");
6456
try
@@ -72,21 +64,27 @@ public async Task CreateRepository(NewRepository newRepository, Action<Octokit.R
7264
}
7365
}
7466

75-
public async Task GetOrganizations(Action<IList<Organization>> callback)
67+
public async Task GetOrganizations(Action<Organization[]> onSuccess, Action<Exception> onError = null)
7668
{
77-
Guard.ArgumentNotNull(callback, "callback");
78-
var organizations = await GetOrganizationInternal();
79-
callback(organizations);
69+
Guard.ArgumentNotNull(onSuccess, nameof(onSuccess));
70+
await GetOrganizationInternal(onSuccess, onError);
8071
}
8172

82-
public async Task LoadKeychain(Action<bool> callback)
73+
public async Task ValidateCurrentUser(Action onSuccess, Action<Exception> onError = null)
8374
{
84-
Guard.ArgumentNotNull(callback, "callback");
85-
var hasLoadedKeys = await LoadKeychainInternal();
86-
callback(hasLoadedKeys);
75+
Guard.ArgumentNotNull(onSuccess, nameof(onSuccess));
76+
try
77+
{
78+
await ValidateCurrentUserInternal();
79+
onSuccess();
80+
}
81+
catch (Exception e)
82+
{
83+
onError?.Invoke(e);
84+
}
8785
}
8886

89-
public async Task GetCurrentUser(Action<Octokit.User> callback)
87+
public async Task GetCurrentUser(Action<GitHubUser> callback)
9088
{
9189
Guard.ArgumentNotNull(callback, "callback");
9290
var user = await GetCurrentUserInternal();
@@ -189,29 +187,27 @@ public async Task<bool> ContinueLoginAsync(LoginResult loginResult, Func<LoginRe
189187
return result.Code == LoginResultCodes.Success;
190188
}
191189

192-
private async Task<Octokit.Repository> CreateRepositoryInternal(NewRepository newRepository, string organization)
190+
private async Task<GitHubRepository> CreateRepositoryInternal(NewRepository newRepository, string organization)
193191
{
194192
try
195193
{
196194
logger.Trace("Creating repository");
197195

198-
if (!await LoadKeychainInternal())
199-
{
200-
throw new InvalidOperationException("The keychain did not load");
201-
}
196+
await ValidateKeychain();
197+
await ValidateCurrentUserInternal();
202198

203-
Octokit.Repository repository;
199+
GitHubRepository repository;
204200
if (!string.IsNullOrEmpty(organization))
205201
{
206202
logger.Trace("Creating repository for organization");
207203

208-
repository = await githubClient.Repository.Create(organization, newRepository);
204+
repository = (await githubClient.Repository.Create(organization, newRepository)).ToGitHubRepository();
209205
}
210206
else
211207
{
212208
logger.Trace("Creating repository for user");
213209

214-
repository = await githubClient.Repository.Create(newRepository);
210+
repository = (await githubClient.Repository.Create(newRepository)).ToGitHubRepository();
215211
}
216212

217213
logger.Trace("Created Repository");
@@ -224,66 +220,78 @@ public async Task<bool> ContinueLoginAsync(LoginResult loginResult, Func<LoginRe
224220
}
225221
}
226222

227-
private async Task<IList<Organization>> GetOrganizationInternal()
223+
private async Task GetOrganizationInternal(Action<Organization[]> onSuccess, Action<Exception> onError = null)
228224
{
229225
try
230226
{
231227
logger.Trace("Getting Organizations");
232228

233-
if (!await LoadKeychainInternal())
234-
{
235-
return new List<Organization>();
236-
}
229+
await ValidateKeychain();
230+
await ValidateCurrentUserInternal();
237231

238232
var organizations = await githubClient.Organization.GetAllForCurrent();
239233

240234
logger.Trace("Obtained {0} Organizations", organizations?.Count.ToString() ?? "NULL");
241235

242236
if (organizations != null)
243237
{
244-
organizationsCache = organizations.ToArray();
238+
var array = organizations.Select(organization => new Organization() {
239+
Name = organization.Name,
240+
Login = organization.Login
241+
}).ToArray();
242+
onSuccess(array);
245243
}
246244
}
247245
catch(Exception ex)
248246
{
249247
logger.Error(ex, "Error Getting Organizations");
250-
throw;
248+
onError?.Invoke(ex);
251249
}
252-
253-
return organizationsCache;
254250
}
255251

256-
private async Task<Octokit.User> GetCurrentUserInternal()
252+
private async Task<GitHubUser> GetCurrentUserInternal()
257253
{
258254
try
259255
{
260-
logger.Trace("Getting Organizations");
261-
262-
if (!await LoadKeychainInternal())
263-
{
264-
return null;
265-
}
256+
logger.Trace("Getting Current User");
257+
await ValidateKeychain();
266258

267-
userCache = await githubClient.User.Current();
259+
return (await githubClient.User.Current()).ToGitHubUser();
268260
}
269-
catch(Exception ex)
261+
catch (KeychainEmptyException)
262+
{
263+
logger.Warning("Keychain is empty");
264+
throw;
265+
}
266+
catch (Exception ex)
270267
{
271268
logger.Error(ex, "Error Getting Current User");
272269
throw;
273270
}
271+
}
272+
273+
private async Task ValidateCurrentUserInternal()
274+
{
275+
logger.Trace("Validating User");
274276

275-
return userCache;
277+
var apiUser = await GetCurrentUserInternal();
278+
var apiUsername = apiUser.Login;
279+
280+
var cachedUsername = keychain.Connections.First().Username;
281+
282+
if (apiUsername != cachedUsername)
283+
{
284+
throw new TokenUsernameMismatchException(cachedUsername, apiUsername);
285+
}
276286
}
277287

278288
private async Task<bool> LoadKeychainInternal()
279289
{
280-
logger.Trace("LoadKeychainInternal");
281-
282290
if (keychain.HasKeys)
283291
{
284292
if (!keychain.NeedsLoad)
285293
{
286-
logger.Trace("LoadKeychainInternal: Has keys does not need load");
294+
logger.Trace("LoadKeychainInternal: Previously Loaded");
287295
return true;
288296
}
289297

@@ -293,6 +301,8 @@ private async Task<bool> LoadKeychainInternal()
293301
var uriString = keychain.Connections.First().Host;
294302
var keychainAdapter = await keychain.Load(uriString);
295303

304+
logger.Trace("LoadKeychainInternal: Loaded");
305+
296306
return keychainAdapter.OctokitCredentials != Credentials.Anonymous;
297307
}
298308

@@ -301,23 +311,54 @@ private async Task<bool> LoadKeychainInternal()
301311
return false;
302312
}
303313

304-
public async Task<bool> ValidateCredentials()
314+
private async Task ValidateKeychain()
305315
{
306-
try
316+
if (!await LoadKeychainInternal())
307317
{
308-
var store = keychain.Connect(OriginalUrl);
309-
310-
if (store.OctokitCredentials != Credentials.Anonymous)
311-
{
312-
var credential = store.Credential;
313-
await githubClient.Authorization.CheckApplicationAuthentication(ApplicationInfo.ClientId, credential.Token);
314-
}
318+
throw new KeychainEmptyException();
315319
}
316-
catch
317-
{
318-
return false;
319-
}
320-
return true;
321320
}
322321
}
322+
323+
class GitHubUser
324+
{
325+
public string Name { get; set; }
326+
public string Login { get; set; }
327+
}
328+
329+
class GitHubRepository
330+
{
331+
public string Name { get; set; }
332+
public string CloneUrl { get; set; }
333+
}
334+
335+
class ApiClientException : Exception
336+
{
337+
public ApiClientException()
338+
{ }
339+
340+
public ApiClientException(string message) : base(message)
341+
{ }
342+
343+
public ApiClientException(string message, Exception innerException) : base(message, innerException)
344+
{ }
345+
}
346+
347+
class TokenUsernameMismatchException : ApiClientException
348+
{
349+
public string CachedUsername { get; }
350+
public string CurrentUsername { get; }
351+
352+
public TokenUsernameMismatchException(string cachedUsername, string currentUsername)
353+
{
354+
CachedUsername = cachedUsername;
355+
CurrentUsername = currentUsername;
356+
}
357+
}
358+
359+
class KeychainEmptyException : ApiClientException
360+
{
361+
public KeychainEmptyException()
362+
{ }
363+
}
323364
}

0 commit comments

Comments
 (0)