-
Notifications
You must be signed in to change notification settings - Fork 313
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
bug: modified password placeholder text depending if remote URI is github (Fix #1176) #1220
Conversation
Thanks for submitting your first pull request! You are awesome! 🤗 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @shawnesquivel
As mentioned in the issue, the trouble here is that this is specific to a Git server policy. For example other providers such GitLab or BitBucket may still allow that authentication system.
This means we need to condition the placeholder with the remote repository URI.
The dialog is spinned there: jupyterlab-git/src/commandsAndMenu.tsx Line 1626 in 1125869
So we could pass the placeholder to the dialog constructor. Now about the remote repository URI, this is gonna be more complex. In the case of a Line 460 in 1125869
Does that make sense? |
Hi @fcollonval! Added some changes + working screenshot. It is working for GitHub but remains as the default 'password / personal access token' otherwise. @basokant also worked with me again on this one, he was a big help! Let me know if there are any other changes to be made. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @shawnesquivel
This is looking good. We now have to improve the url search depending on the operation to be carried out.
src/widgets/CredentialsBox.tsx
Outdated
@@ -10,13 +10,16 @@ export class GitCredentialsForm | |||
extends Widget | |||
implements Dialog.IBodyWidget<Git.IAuth> | |||
{ | |||
passwordPlaceholder: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Purely styling comment:
Could you place this attribute at the bottom of the class with the other attributes and make it private (with the convention of starting with _
)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. I assume _
is only for the private property, so I didn't change it on the parameter.
src/commandsAndMenu.tsx
Outdated
const result = remoteURI[0]?.url.match(re); | ||
const gitProvider = result[1]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Result may be undefined so you should protect the code against that; something like:
const result = remoteURI[0]?.url.match(re); | |
const gitProvider = result[1]; | |
const result = remoteURI[0]?.url.match(re) ?? []; | |
const gitProvider = result[1]; |
src/commandsAndMenu.tsx
Outdated
const remoteURI = await model.getRemotes().then(remote => { | ||
return remote; | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good this is the idea indeed. But now we need to be smart depending on the operation
type. If the operation is Operation.Clone
, we don't need to request the remotes as we can look directly at args.url
. In the cases of push and pull, we should not take remoteURI[0]
but we should find the item matching args.remote
. Then for the fetch case, let's use your fallback of only testing remoteURI[0]
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For Pull:
Pull - I tried accessing args. When logging it, I noticed args is an empty object (no remote property), so I passed it in using the code below, which showed me that args.remote = 'origin'. But I don't think I fully understand what you mean by 'finding the item matching args.remote', do you mind explaining further? I guess I just don't see how the args.remote is going to tell us that the git provider is github (if that was what you were suggesting).
commandsAndMenu.tsx Line 383
/** Add git pull command */
commands.addCommand(CommandIDs.gitPull, {
execute: async args => {
try {
// copy how commandIDS.gitPush grabs remote
let remote;
const result = await showDialog({
title: trans.__('Please select push options.'),
body: new AdvancedPushForm(trans, gitModel),
buttons: [
Dialog.cancelButton({ label: trans.__('Cancel') }),
Dialog.okButton({ label: trans.__('Proceed') })
]
});
remote = result.value.remoteName;
// added args as an additional param
const details = await showGitOperationDialog(
gitModel,
Operation.Pull,
trans,
(args = { remote })
);
For Push
- By default, args is an object with remote property, but it was undefined. So, maybe args.remote is not defined if we're not authenticated?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
git
uses name for remote to be more user friendly. Then it uses a db to get the URI from the name.
You can see that by executing in a terminal git remote -vv
; the output will look like:
origin git@github.com:fcollonval/jupyterlab.git (fetch)
origin git@github.com:fcollonval/jupyterlab.git (push)
trungleduc https://github.com/trungleduc/jupyterlab (fetch)
trungleduc https://github.com/trungleduc/jupyterlab (push)
upstream https://github.com/jupyterlab/jupyterlab.git (fetch)
upstream https://github.com/jupyterlab/jupyterlab.git (push)
Name origin
refers git@github.com:fcollonval/jupyterlab.git
in the above example.
As you discover (:clap: for that), you could get the name passing the remote
variable. But to determine the associated URI, you first need to call getRemote
(as you have done already). It returns you an array of Git.IGitRemote
. That interface has the following definition:
interface IGitRemote {
url: string;
name: string;
}
So now that you know remote
you need to find the IGitRemote
object in the array with that name. Then you will be able to test the URL.
Does it clarify what you need to do?
Regarding push, if it is undefined, you could still apply the same logic and fallback to remoteURI[0].url
if it is undefined.
We could improve this by having the backend tell use which of the remote is the default. But let's try not to increase the scope of this PR too much.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @fcollonval !
Yes this was a very thorough explanation, thank you!
I was able to add the edits you requested for pull, push, clone, and fetch.
I have some more questions:
- How do I test git fetch?
- I tried using
git fetch -all
which returned 'Fetching origin' - However, it didn't throw any errors even though we are not authenticated, so I'm not sure how to proceed.
- In git pull, I passed the args to the git-pull catch block by using the following code. It's wrong since it creates an unnecessary dialog box just to get the current remote name. Is there some other way of getting the current remote name? If not, I'll just remove this section as there are fallbacks in place already.
let remote;
const result = await showDialog({
title: trans.__('Please select push options.'),
body: new AdvancedPushForm(trans, gitModel),
buttons: [
Dialog.cancelButton({ label: trans.__('Cancel') }),
Dialog.okButton({ label: trans.__('Proceed') })
]
});
remote = result.value.remoteName;
- I grouped git pull, push and force in the catch block because that made sense to me, but there may be some nuances here that I'm overlooking.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @shawnesquivel
Here are some comments and suggestions
src/commandsAndMenu.tsx
Outdated
// copy how gitPush grabs remote - this needs to be fixed as it creates a Git Push UI | ||
// is there a better way to grab the remoteName? | ||
const result = await showDialog({ | ||
title: trans.__('Please select push options.'), | ||
body: new AdvancedPushForm(trans, gitModel), | ||
buttons: [ | ||
Dialog.cancelButton({ label: trans.__('Cancel') }), | ||
Dialog.okButton({ label: trans.__('Proceed') }) | ||
] | ||
}); | ||
const remote = result.value.remoteName; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed this is not great.
As pulling concerned the current branch, you could introspect gitModel.currentBranch.upstream
. If it exists it should start with the remote name; as seen in the example:
upstream: 'origin/patch-007', |
src/commandsAndMenu.tsx
Outdated
// 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.') : '', | ||
trans.__(gitPasswordPlaceholder) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This unfortunately will not work as expected. To figure out all the string that requires translation, we cannot rely on executing the code as it may be very complex to get the application in all possible state. So the strings are extracted from a static analysis of the code; i.e. all string passed to trans.__
(and similar) are extracted in the to be localized string database. This means that you need to wrap the constant strings you are setting gitPasswordPlaceholder
with (i.e. lines 1667 and 1714).
trans.__(gitPasswordPlaceholder) | |
gitPasswordPlaceholder |
src/widgets/CredentialsBox.tsx
Outdated
constructor( | ||
trans: TranslationBundle, | ||
textContent = trans.__('Enter credentials for remote repository'), | ||
warningContent = '' | ||
warningContent = '', | ||
passwordPlaceholder = 'password / personal access token' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the reason explain earlier.
passwordPlaceholder = 'password / personal access token' | |
passwordPlaceholder = trans.__('password / personal access token') |
src/widgets/CredentialsBox.tsx
Outdated
this._password.placeholder = this._trans.__( | ||
'password / personal access token' | ||
); | ||
this._password.placeholder = this._trans.__(this._passwordPlaceholder); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this._password.placeholder = this._trans.__(this._passwordPlaceholder); | |
this._password.placeholder = this._passwordPlaceholder; |
Co-authored-by: Frédéric Collonval <fcollonval@users.noreply.github.com>
…lab-git into issue-1176 merged changes
@fcollonval, looks like the tests are passing now! I still haven't tested git fetch yet though as per my previous comment. Everything else seems to be working. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @shawnesquivel
I added two comments for alternative ways. But the code is good as is. So I'm gonna merge.
if (currentRemote) { | ||
return currentRemote?.url; | ||
} else { | ||
return ''; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI you could have use a denser code:
if (currentRemote) { | |
return currentRemote?.url; | |
} else { | |
return ''; | |
} | |
return currentRemote?.url ?? ''; |
break; | ||
} | ||
// GitHub only verifies with personal access tokens | ||
if (remoteGitProvider && remoteGitProvider.toLowerCase() === 'github') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI you do not need to test for remoteGitProvider
being defined and not empty string. The second test is sufficient.
if (remoteGitProvider && remoteGitProvider.toLowerCase() === 'github') { | |
if (remoteGitProvider.toLowerCase() === 'github') { |
This fixes #1176.
Description of Changes
Git Push
Git.Push.mov
Git Clone
Git.Clone.mov
Git Pull
Git.Pull.mov
Collaborated with @basokant on this!