-
Notifications
You must be signed in to change notification settings - Fork 406
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
fix: flushFilePath() with fix for Windows #4362
Conversation
This PR was originally #4240, but needed to be backed out due to an issue running on Windows. I looked into the issue, and it was b/c under Windows, |
|
||
const exampleJsonString = JSON.stringify({ name: 'exampleName', error: 'exampleError' }); | ||
const exampleJsonString = JSON.stringify({ | ||
name: 'exampleName', |
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.
Note: there's a lot of format changes here in this PR. This was not my doing. When I save files, they are automatically being re-formatted. I'm not sure if there was a recent configuration change, but it seems like we have a lot of formatting changes in PRs lately.
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.
I've seen this also. Checked in w Gordon about it yesterday. We're going to create a ticket to look into why this is happening.
fsPath: sourceUri.fsPath | ||
} | ||
); | ||
await vscode.commands.executeCommand('sfdx.launch.replay.debugger.logfile', { |
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.
more auto-formatting changes...
import { | ||
forceAnonApexDebug | ||
} from './forceAnonApexExecute'; | ||
import { testOutlineProvider } from '../views/testOutlineProvider'; |
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.
more auto-formatting changes...
// causes problems further down stream. To fix this, we'll use the path | ||
// returned from fs.realpathSync.native() and then capitalize the first | ||
// character. | ||
nativePath = nativePath.charAt(0).toLowerCase() + nativePath.slice(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.
👍🏽
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.
stupid questions b/c windows. The default is C:\ but can a user have a drive named a lower case letter? So would d:\ be valid vs D:? There may be a corner case here were a drive is actually a lower case letter (a quick google told me this does happen in some instances, like when using a usb drive). We probably need a follow on ticket here to address the corner case and having the ability to ask the filesystem the valid path.
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.
From what I can tell, what's displayed is always uppercase (D:\
) but what the APIs/SDK uses is always lowercase (d:\
). I tested this on a VM running Windows, but it's VERY slow, so I'd like a more thorough test on a real Windows machine b/f we merge.
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.
(also, if I remember correctly, Windows is case-insensitive, so d:\
is the same as D:\
. When one performs a FileExists("c:\\foo\\bar.txt")
, it's the same as FileExists("C:\\FOO\\BAR.TXT")
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.
I'm full of dumb questions. With the case insensitivity of windows why are we required to make the above change? It's been too long I don't remember what the 'down stream' changes are that result in the issue.
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.
That's a really good question, and I wondered about that as well, but unfortunately, I don't know why the casing is failing. When I was debugging this, I noticed that the path was "c:\bla\bla\bla.cls" but fs.realpathSync.native() was returning "C:\bla\bla\bla.cls", and when I changed the case for the first char (the drive letter), our actions (deploy, delete, etc...) worked again.
|
||
const result = flushFilePath(filePath); | ||
|
||
expect(realpathSyncNativeStub.called).to.equal(true); |
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.
Since calledOnce is used below, is the expect for "called" needed here?
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.
I wrote this a while ago... I think at the time my thought was, _"test & verify that it was called... ...AND test & verify that it was only called once"..., but I think you are right, in that it might be a bit redundant. I'll go & remove it.
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.
+1 nice catch
|
||
expect(result).to.equal(filePaths); | ||
|
||
realpathSyncNativeStub.restore(); |
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.
Would this restore() be better placed in an afterEach() block? Or do you prefer to keep it here inside each test case block?
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 moment, there's only one test, so I think keeping it central to the test is better. If there were more tests, and that stub was used in every test (and the stubbed value never changed), then placing it in beforeEach
would be a better place, but for here & now, probably best to keep it where it is.
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.
+1
Seems you could move the stub into a beforeEach and the restore into an afterEach FTW
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.
hum... I can't tell from the formatting but the flushFilePath
and flushFilePaths
describe blocks both appear to have tests that create and restore the following stub
.stub(fs.realpathSync, 'native')
.returns(realpathSyncFilePath);
...
realpathSyncNativeStub.restore();
should those not be consolidated? I typically lean towards following patterns in tests to make them easier to grok for both new and existing developers so I'd prefer we put the stub/restore in before/after each blocks. This could be at the top level describe if that makes sense or just in a describe wrapper for all flushFilePath*
describe blocks.
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.
oh..above I mean I couldn't tell if both describe blocks were wrapped in a single top level describe.
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.
@gbockus-sf maybe we should take this off line & discuss f2f. realpathSyncNativeStub can't be hoisted or shared, b/c the mocked value that's returned changes from test to test.
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.
@jeffb-sfdc Sure I'll ping ya in slack
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.
I wrapped everything in a describe()
, added a beforeEach()
and afterEach()
, and moved realpathSyncNativeStub
// but it actually it returns string | undefined. Well, regardless, since flushFilePath() takes | ||
// a string (and guards against empty strings) using the Non-null assertion operator | ||
// (https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html#non-null-assertion-operator) | ||
// fixes the issue. |
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.
👍🏽
}); | ||
}); | ||
|
||
describe('ConfirmationAndSourcePathGatherer', () => { | ||
const examplePath = path.join('example', 'path'); | ||
const explorerPath = { fsPath: examplePath } as vscode.Uri; | ||
const explorerPathUri = { fsPath: examplePath } as vscode.Uri; |
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.
👍🏽
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.
Looks good to me @jeffb-sfdc ! Left one question about maybe using afterEach in the tests, up to you for consideration.
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.
One concerning point of discussion around windows machines that have a lower case letter drive.
I ran the same tests on M1 Mac as on the last PR, all checks out: ✅ SFDX: Deploy Source to Org works after renaming locally by only making changes to the casing in the file+class name |
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.
changes look good 👍
✅ verified on windows
Also attempted to create a volume to check the lower case volume letter and found it wasn't possible using the out of the box disk manager for windows so I think we're good to go 👍
What does this PR do?
There's a bug in VS Code, which Microsoft refuses to fix (see microsoft/vscode#152993). After a file has been renamed, if only the casing has changes (eg no characters added or removed) VS Code passes the stale path to commands. This PR adds
flushFilePath()
andflushFilePaths()
to fix this issue.What issues does this PR fix or reference?
##3575, @W-10273785@
Functionality Before
Functionality After
1-3: the same
4. This deployment succeeds