Skip to content

Commit

Permalink
bug: modified password placeholder text depending if remote URI is gi…
Browse files Browse the repository at this point in the history
…thub (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 <[email protected]>

* updated translation strings and simplified gitPull

* make variable names more descriptive

---------

Co-authored-by: Frédéric Collonval <[email protected]>
  • Loading branch information
shawnesquivel and fcollonval authored Mar 3, 2023
1 parent 92a9626 commit 1ecee9d
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 7 deletions.
1 change: 1 addition & 0 deletions src/cloneCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export const gitCloneCommandPlugin: JupyterFrontEndPlugin<void> = {
level: Level.ERROR,
error: error as Error
});
throw error;
}
}
}
Expand Down
78 changes: 76 additions & 2 deletions src/commandsAndMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1571,6 +1571,36 @@ export async function showGitOperationDialog<T>(
authentication?: Git.IAuth,
retry = false
): Promise<string> {
/**
* Returns the current remote's URL based on the current remote name and all the remotes
*/
async function getCurrentRemote(currentRemoteName: string): Promise<string> {
const remoteList = await model.getRemotes().then(remoteList => {
return remoteList;
});

const currentRemote = remoteList.find(
remoteURI => remoteURI.name === currentRemoteName
);

if (currentRemote) {
return currentRemote?.url;
} else {
return '';
}
}

/**
* Returns the Git provider based on the domain name of the url
*/
function getGitProviderHost(remoteUrl: string): string {
// Regex returns the word between "https" and "."
const re = /https:\/\/([^.]+)\./;
const result = remoteUrl.match(re) ?? [];
const gitProvider = result[1];
return gitProvider;
}

try {
let result: Git.IResultWithMessage;
// the Git action
Expand Down Expand Up @@ -1612,21 +1642,65 @@ export async function showGitOperationDialog<T>(
result = { code: -1, message: 'Unknown git command' };
break;
}

return result.message;
} catch (error) {
if (
AUTH_ERROR_MESSAGES.some(
errorMessage => (error as Error).message.indexOf(errorMessage) > -1
)
) {
// Change the placeholder message for GitHub
let gitPasswordPlaceholder = trans.__('password / personal access token');
let remoteGitProvider = '';

switch (operation) {
case Operation.Clone:
// eslint-disable-next-line no-case-declarations
const { url: encodedArgsUrl } = args as any as IGitCloneArgs;
remoteGitProvider = getGitProviderHost(
decodeURIComponent(encodedArgsUrl)
);
break;
case Operation.Push:
case Operation.ForcePush:
case Operation.Pull:
// If the remote is defined, check it against the remote URI list
if (model.currentBranch.upstream) {
// Compare the remote against the URI list
const remoteName = model.currentBranch.upstream.split('/')[0];
const currentRemoteUrl = await getCurrentRemote(remoteName);
remoteGitProvider = currentRemoteUrl
? getGitProviderHost(currentRemoteUrl)
: '';
} else {
// if the remote is undefined, use first remote URI
const remoteList = await model.getRemotes().then(remoteList => {
return remoteList;
});
remoteGitProvider = getGitProviderHost(remoteList[0]?.url);
}
break;

case Operation.Fetch:
remoteGitProvider = await model
.getRemotes()
.then(remoteList => remoteList[0]?.url);
break;
default:
break;
}
// GitHub only verifies with personal access tokens
if (remoteGitProvider && remoteGitProvider.toLowerCase() === 'github') {
gitPasswordPlaceholder = trans.__('personal access token');
}
// If the error is an authentication error, ask the user credentials
const credentials = await showDialog({
title: trans.__('Git credentials required'),
body: new GitCredentialsForm(
trans,
trans.__('Enter credentials for remote repository'),
retry ? trans.__('Incorrect username or password.') : ''
retry ? trans.__('Incorrect username or password.') : '',
gitPasswordPlaceholder
)
});

Expand Down
3 changes: 2 additions & 1 deletion src/git.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import { Git } from './tokens';
export const AUTH_ERROR_MESSAGES = [
'Invalid username or password',
'could not read Username',
'could not read Password'
'could not read Password',
'Authentication error'
];

/**
Expand Down
6 changes: 6 additions & 0 deletions src/tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,12 @@ export interface IGitExtension extends IDisposable {
*/
getRelativeFilePath(path?: string): string | null;

/**
* Show remote repository for the current repository
* @returns promise which resolves to a list of remote repositories
*/
getRemotes(): Promise<Git.IGitRemote[]>;

/**
* Add an entry in .gitignore file
*
Expand Down
9 changes: 5 additions & 4 deletions src/widgets/CredentialsBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,16 @@ export class GitCredentialsForm
extends Widget
implements Dialog.IBodyWidget<Git.IAuth>
{
private _passwordPlaceholder: string;
constructor(
trans: TranslationBundle,
textContent = trans.__('Enter credentials for remote repository'),
warningContent = ''
warningContent = '',
passwordPlaceholder = trans.__('password / personal access token')
) {
super();
this._trans = trans;
this._passwordPlaceholder = passwordPlaceholder;
this.node.appendChild(this.createBody(textContent, warningContent));
}

Expand All @@ -41,9 +44,7 @@ export class GitCredentialsForm
text.textContent = textContent;
warning.textContent = warningContent;
this._user.placeholder = this._trans.__('username');
this._password.placeholder = this._trans.__(
'password / personal access token'
);
this._password.placeholder = this._passwordPlaceholder;

checkboxLabel.className = 'jp-CredentialsBox-label-checkbox';
this._checkboxCacheCredentials.type = 'checkbox';
Expand Down

0 comments on commit 1ecee9d

Please sign in to comment.