Skip to content

Commit 1ecee9d

Browse files
bug: modified password placeholder text depending if remote URI is github (Fix #1176) (#1220)
* modified password placeholder text to only include PAT * changed placeholder text if remote URI matches github https * removed redundant type annotation * get remote for no-auth git pull * cleaned code and added catch for git clone * removed comment * removed old code * fixed no-case-declarations error in the catch switch block * fixed and ignored no-case-declaration errors * removed redundant type annotation * Update src/commandsAndMenu.tsx Co-authored-by: Frédéric Collonval <fcollonval@users.noreply.github.com> * updated translation strings and simplified gitPull * make variable names more descriptive --------- Co-authored-by: Frédéric Collonval <fcollonval@users.noreply.github.com>
1 parent 92a9626 commit 1ecee9d

File tree

5 files changed

+90
-7
lines changed

5 files changed

+90
-7
lines changed

src/cloneCommand.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ export const gitCloneCommandPlugin: JupyterFrontEndPlugin<void> = {
7979
level: Level.ERROR,
8080
error: error as Error
8181
});
82+
throw error;
8283
}
8384
}
8485
}

src/commandsAndMenu.tsx

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1571,6 +1571,36 @@ export async function showGitOperationDialog<T>(
15711571
authentication?: Git.IAuth,
15721572
retry = false
15731573
): Promise<string> {
1574+
/**
1575+
* Returns the current remote's URL based on the current remote name and all the remotes
1576+
*/
1577+
async function getCurrentRemote(currentRemoteName: string): Promise<string> {
1578+
const remoteList = await model.getRemotes().then(remoteList => {
1579+
return remoteList;
1580+
});
1581+
1582+
const currentRemote = remoteList.find(
1583+
remoteURI => remoteURI.name === currentRemoteName
1584+
);
1585+
1586+
if (currentRemote) {
1587+
return currentRemote?.url;
1588+
} else {
1589+
return '';
1590+
}
1591+
}
1592+
1593+
/**
1594+
* Returns the Git provider based on the domain name of the url
1595+
*/
1596+
function getGitProviderHost(remoteUrl: string): string {
1597+
// Regex returns the word between "https" and "."
1598+
const re = /https:\/\/([^.]+)\./;
1599+
const result = remoteUrl.match(re) ?? [];
1600+
const gitProvider = result[1];
1601+
return gitProvider;
1602+
}
1603+
15741604
try {
15751605
let result: Git.IResultWithMessage;
15761606
// the Git action
@@ -1612,21 +1642,65 @@ export async function showGitOperationDialog<T>(
16121642
result = { code: -1, message: 'Unknown git command' };
16131643
break;
16141644
}
1615-
16161645
return result.message;
16171646
} catch (error) {
16181647
if (
16191648
AUTH_ERROR_MESSAGES.some(
16201649
errorMessage => (error as Error).message.indexOf(errorMessage) > -1
16211650
)
16221651
) {
1652+
// Change the placeholder message for GitHub
1653+
let gitPasswordPlaceholder = trans.__('password / personal access token');
1654+
let remoteGitProvider = '';
1655+
1656+
switch (operation) {
1657+
case Operation.Clone:
1658+
// eslint-disable-next-line no-case-declarations
1659+
const { url: encodedArgsUrl } = args as any as IGitCloneArgs;
1660+
remoteGitProvider = getGitProviderHost(
1661+
decodeURIComponent(encodedArgsUrl)
1662+
);
1663+
break;
1664+
case Operation.Push:
1665+
case Operation.ForcePush:
1666+
case Operation.Pull:
1667+
// If the remote is defined, check it against the remote URI list
1668+
if (model.currentBranch.upstream) {
1669+
// Compare the remote against the URI list
1670+
const remoteName = model.currentBranch.upstream.split('/')[0];
1671+
const currentRemoteUrl = await getCurrentRemote(remoteName);
1672+
remoteGitProvider = currentRemoteUrl
1673+
? getGitProviderHost(currentRemoteUrl)
1674+
: '';
1675+
} else {
1676+
// if the remote is undefined, use first remote URI
1677+
const remoteList = await model.getRemotes().then(remoteList => {
1678+
return remoteList;
1679+
});
1680+
remoteGitProvider = getGitProviderHost(remoteList[0]?.url);
1681+
}
1682+
break;
1683+
1684+
case Operation.Fetch:
1685+
remoteGitProvider = await model
1686+
.getRemotes()
1687+
.then(remoteList => remoteList[0]?.url);
1688+
break;
1689+
default:
1690+
break;
1691+
}
1692+
// GitHub only verifies with personal access tokens
1693+
if (remoteGitProvider && remoteGitProvider.toLowerCase() === 'github') {
1694+
gitPasswordPlaceholder = trans.__('personal access token');
1695+
}
16231696
// If the error is an authentication error, ask the user credentials
16241697
const credentials = await showDialog({
16251698
title: trans.__('Git credentials required'),
16261699
body: new GitCredentialsForm(
16271700
trans,
16281701
trans.__('Enter credentials for remote repository'),
1629-
retry ? trans.__('Incorrect username or password.') : ''
1702+
retry ? trans.__('Incorrect username or password.') : '',
1703+
gitPasswordPlaceholder
16301704
)
16311705
});
16321706

src/git.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ import { Git } from './tokens';
99
export const AUTH_ERROR_MESSAGES = [
1010
'Invalid username or password',
1111
'could not read Username',
12-
'could not read Password'
12+
'could not read Password',
13+
'Authentication error'
1314
];
1415

1516
/**

src/tokens.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,12 @@ export interface IGitExtension extends IDisposable {
360360
*/
361361
getRelativeFilePath(path?: string): string | null;
362362

363+
/**
364+
* Show remote repository for the current repository
365+
* @returns promise which resolves to a list of remote repositories
366+
*/
367+
getRemotes(): Promise<Git.IGitRemote[]>;
368+
363369
/**
364370
* Add an entry in .gitignore file
365371
*

src/widgets/CredentialsBox.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,16 @@ export class GitCredentialsForm
1010
extends Widget
1111
implements Dialog.IBodyWidget<Git.IAuth>
1212
{
13+
private _passwordPlaceholder: string;
1314
constructor(
1415
trans: TranslationBundle,
1516
textContent = trans.__('Enter credentials for remote repository'),
16-
warningContent = ''
17+
warningContent = '',
18+
passwordPlaceholder = trans.__('password / personal access token')
1719
) {
1820
super();
1921
this._trans = trans;
22+
this._passwordPlaceholder = passwordPlaceholder;
2023
this.node.appendChild(this.createBody(textContent, warningContent));
2124
}
2225

@@ -41,9 +44,7 @@ export class GitCredentialsForm
4144
text.textContent = textContent;
4245
warning.textContent = warningContent;
4346
this._user.placeholder = this._trans.__('username');
44-
this._password.placeholder = this._trans.__(
45-
'password / personal access token'
46-
);
47+
this._password.placeholder = this._passwordPlaceholder;
4748

4849
checkboxLabel.className = 'jp-CredentialsBox-label-checkbox';
4950
this._checkboxCacheCredentials.type = 'checkbox';

0 commit comments

Comments
 (0)