-
Notifications
You must be signed in to change notification settings - Fork 29.2k
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
show symbolic links as decorations in explorer #43815
Conversation
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.
@isidorn some feedback provided
@@ -410,6 +410,11 @@ export interface IFileStat extends IBaseStat { | |||
*/ | |||
isDirectory: boolean; | |||
|
|||
/** | |||
* The resource is a simbolic link. |
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.
simbolic => symbolic
@@ -19,7 +19,7 @@ function create(relativePath: string): StatResolver { | |||
let absolutePath = relativePath ? path.join(basePath, relativePath) : basePath; | |||
let fsStat = fs.statSync(absolutePath); | |||
|
|||
return new StatResolver(uri.file(absolutePath), fsStat.isDirectory(), fsStat.mtime.getTime(), fsStat.size, void 0); | |||
return new StatResolver(uri.file(absolutePath), fsStat.isSymbolicLink(), fsStat.isDirectory(), fsStat.mtime.getTime(), fsStat.size, void 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.
@isidorn can we have a test for this too? it looks like node.js allows to create symlinks (fs.symlink
).
if (fileStat && fileStat.nonexistentRoot) { | ||
return { | ||
tooltip: localize('canNotResolve', "Can not resolve workspace folder"), | ||
letter: '!', | ||
color: listInvalidItemForeground, | ||
}; | ||
} | ||
if (fileStat && fileStat.isSymbolicLink) { | ||
return { | ||
tooltip: localize('symbolicLlink', "Symbolic link"), |
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.
Maybe better capital casing: Symbolic Link
if (fileStat && fileStat.isSymbolicLink) { | ||
return { | ||
tooltip: localize('symbolicLlink', "Symbolic link"), | ||
letter: '\u21f2' |
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.
@@ -1254,6 +1259,7 @@ export class StatResolver { | |||
const childStat: IFileStat = { | |||
resource: fileResource, | |||
isDirectory: fileStat.isDirectory(), | |||
isSymbolicLink: isSymbolicLink, |
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.
Can be simplified to: isSymbolicLink
@@ -913,7 +913,7 @@ export class FileService implements IFileService { | |||
const absolutePath = this.toAbsolutePath(resource); | |||
|
|||
return pfs.stat(absolutePath).then(stat => { | |||
return new StatResolver(resource, stat.isDirectory(), stat.mtime.getTime(), stat.size, this.options.verboseLogging ? this.options.errorLogger : void 0); | |||
return new StatResolver(resource, false, stat.isDirectory(), stat.mtime.getTime(), stat.size, this.options.verboseLogging ? this.options.errorLogger : void 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.
This is a bit weird, why not introduce a new method pfs.statLink
that is implemented like this:
- executes
lstat
- executes
stat
only if the stat is a symbolic link - returns something like
{ stat: stat, isSymbolicLink: boolean }
This method could then also be used from within the resolver
@@ -1235,7 +1233,14 @@ export class StatResolver { | |||
}, | |||
|
|||
function stat(this: any): void { | |||
fs.stat(fileResource.fsPath, this); | |||
fs.lstat(fileResource.fsPath, (error, stat) => { |
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.
Use the new method from extfs/pfs for this.
@bpasero I have addressed all your comments. Please review when you get a chance |
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.
@isidorn feel free to commit after checking out my changes
@@ -912,8 +912,8 @@ export class FileService implements IFileService { | |||
private toStatResolver(resource: uri): TPromise<StatResolver> { | |||
const absolutePath = this.toAbsolutePath(resource); | |||
|
|||
return pfs.stat(absolutePath).then(stat => { | |||
return new StatResolver(resource, stat.isDirectory(), stat.mtime.getTime(), stat.size, this.options.verboseLogging ? this.options.errorLogger : void 0); | |||
return pfs.statLink(absolutePath).then(statAndIsLink => { |
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.
Can be written nicer:
return pfs.statLink(absolutePath).then(({ isSymbolicLink, stat }) => {
return new StatResolver(resource, isSymbolicLink, stat.isDirectory(), stat.mtime.getTime(), stat.size, this.options.verboseLogging ? this.options.errorLogger : void 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.
Done
@@ -1235,7 +1233,10 @@ export class StatResolver { | |||
}, | |||
|
|||
function stat(this: any): void { | |||
fs.stat(fileResource.fsPath, this); | |||
extfs.statLink(fileResource.fsPath, (error: Error, statAndIsLink) => { |
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.
Can be nicer:
extfs.statLink(fileResource.fsPath, (error: Error, { stat, isSymbolicLink }) => {
isSymbolicLink = isSymbolicLink;
this(null, stat);
});
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.
Did not do this due to name clash of the isSymoblicLink variable a couple of lines up. Decided to leave like it is.
@@ -54,6 +54,16 @@ export function stat(path: string): TPromise<fs.Stats> { | |||
return nfcall(fs.stat, path); | |||
} | |||
|
|||
export function statLink(path: string): TPromise<{ stat: fs.Stats, isSymbolicLink: boolean }> { |
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.
@isidorn why is this method not simply using extfs
? E.g. it should be as simple as:
export function statLink(path: string): TPromise<string> {
return nfcall(extfs.statLink, 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.
@bpasero you are correct. I was not aware I can depend on extfs
in pfs
, but now I see it is already done.
Fixed
fixes #11539
I have adopted your idea in the
fileService
to first do anlstat
and if only if it is a symbolic link to do an additionalstat
call.As for visualisation to not do any icon crazyness I have decided to use decorations similar to what we do for errors and git decorations.
I went through all the ansi arrows and I personally like this one the most ⇲
Here's a list of unicode arrows https://unicode-table.com/en/sets/arrows-symbols/
After we get feedback from users we can decide to do some additional decorating like italic, but not for now imho and also the decoration api does not support italic
fyi @chryw
A nice icon overlay you provided looks great, we can look into adding that to the icon as step 2, after we merge this is and get some feedback.