4
4
*--------------------------------------------------------------------------------------------*/
5
5
6
6
import { Event } from 'vs/base/common/event' ;
7
- import { toSlashes } from 'vs/base/common/extpath' ;
7
+ import { isUNC , toSlashes } from 'vs/base/common/extpath' ;
8
8
import * as json from 'vs/base/common/json' ;
9
9
import * as jsonEdit from 'vs/base/common/jsonEdit' ;
10
10
import { FormattingOptions } from 'vs/base/common/jsonFormatter' ;
11
11
import { normalizeDriveLetter } from 'vs/base/common/labels' ;
12
12
import { Schemas } from 'vs/base/common/network' ;
13
- import { isAbsolute } from 'vs/base/common/path' ;
13
+ import { isAbsolute , posix } from 'vs/base/common/path' ;
14
14
import { isLinux , isMacintosh , isWindows } from 'vs/base/common/platform' ;
15
15
import { IExtUri , isEqualAuthority } from 'vs/base/common/resources' ;
16
16
import { URI } from 'vs/base/common/uri' ;
@@ -124,55 +124,77 @@ export interface IEnterWorkspaceResult {
124
124
}
125
125
126
126
/**
127
- * Given a folder URI and the workspace config folder, computes the IStoredWorkspaceFolder using
128
- * a relative or absolute path or a uri.
129
- * Undefined is returned if the folderURI and the targetConfigFolderURI don't have the same schema or authority
127
+ * Given a folder URI and the workspace config folder, computes the `IStoredWorkspaceFolder`
128
+ * using a relative or absolute path or a uri.
129
+ * Undefined is returned if the `folderURI` and the `targetConfigFolderURI` don't have the
130
+ * same schema or authority.
130
131
*
131
132
* @param folderURI a workspace folder
132
133
* @param forceAbsolute if set, keep the path absolute
133
134
* @param folderName a workspace name
134
135
* @param targetConfigFolderURI the folder where the workspace is living in
135
- * @param useSlashForPath if set, use forward slashes for file paths on windows
136
136
*/
137
- export function getStoredWorkspaceFolder ( folderURI : URI , forceAbsolute : boolean , folderName : string | undefined , targetConfigFolderURI : URI , useSlashForPath = ! isWindows , extUri : IExtUri ) : IStoredWorkspaceFolder {
137
+ export function getStoredWorkspaceFolder ( folderURI : URI , forceAbsolute : boolean , folderName : string | undefined , targetConfigFolderURI : URI , extUri : IExtUri ) : IStoredWorkspaceFolder {
138
+
139
+ // Scheme mismatch: use full absolute URI as `uri`
138
140
if ( folderURI . scheme !== targetConfigFolderURI . scheme ) {
139
141
return { name : folderName , uri : folderURI . toString ( true ) } ;
140
142
}
141
143
144
+ // Always prefer a relative path if possible unless
145
+ // prevented to make the workspace file shareable
146
+ // with other users
142
147
let folderPath = ! forceAbsolute ? extUri . relativePath ( targetConfigFolderURI , folderURI ) : undefined ;
143
148
if ( folderPath !== undefined ) {
144
149
if ( folderPath . length === 0 ) {
145
150
folderPath = '.' ;
146
- } else if ( isWindows && folderURI . scheme === Schemas . file && ! useSlashForPath ) {
147
- // Windows gets special treatment:
148
- // - use backslahes unless slash is used by other existing folders
149
- folderPath = folderPath . replace ( / \/ / g , '\\' ) ;
151
+ } else {
152
+ if ( isWindows ) {
153
+ folderPath = massagePathForWindows ( folderPath ) ;
154
+ }
150
155
}
151
- } else {
156
+ }
152
157
153
- // use absolute path
158
+ // We could not resolve a relative path
159
+ else {
160
+
161
+ // Local file: use `fsPath`
154
162
if ( folderURI . scheme === Schemas . file ) {
155
163
folderPath = folderURI . fsPath ;
156
164
if ( isWindows ) {
157
- // Windows gets special treatment:
158
- // - normalize all paths to get nice casing of drive letters
159
- // - use backslahes unless slash is used by other existing folders
160
- folderPath = normalizeDriveLetter ( folderPath ) ;
161
- if ( useSlashForPath ) {
162
- folderPath = toSlashes ( folderPath ) ;
163
- }
164
- }
165
- } else {
166
- if ( ! extUri . isEqualAuthority ( folderURI . authority , targetConfigFolderURI . authority ) ) {
167
- return { name : folderName , uri : folderURI . toString ( true ) } ;
165
+ folderPath = massagePathForWindows ( folderPath ) ;
168
166
}
167
+ }
168
+
169
+ // Different authority: use full absolute URI
170
+ else if ( ! extUri . isEqualAuthority ( folderURI . authority , targetConfigFolderURI . authority ) ) {
171
+ return { name : folderName , uri : folderURI . toString ( true ) } ;
172
+ }
173
+
174
+ // Non-local file: use `path` of URI
175
+ else {
169
176
folderPath = folderURI . path ;
170
177
}
171
178
}
172
179
173
180
return { name : folderName , path : folderPath } ;
174
181
}
175
182
183
+ function massagePathForWindows ( folderPath : string ) {
184
+
185
+ // Drive letter should be upper case
186
+ folderPath = normalizeDriveLetter ( folderPath ) ;
187
+
188
+ // Always prefer slash over backslash unless
189
+ // we deal with UNC paths where backslash is
190
+ // mandatory.
191
+ if ( ! isUNC ( folderPath ) ) {
192
+ folderPath = toSlashes ( folderPath ) ;
193
+ }
194
+
195
+ return folderPath ;
196
+ }
197
+
176
198
export function toWorkspaceFolders ( configuredFolders : IStoredWorkspaceFolder [ ] , workspaceConfigFile : URI , extUri : IExtUri ) : WorkspaceFolder [ ] {
177
199
const result : WorkspaceFolder [ ] = [ ] ;
178
200
const seen : Set < string > = new Set ( ) ;
@@ -187,8 +209,8 @@ export function toWorkspaceFolders(configuredFolders: IStoredWorkspaceFolder[],
187
209
} else if ( isRawUriWorkspaceFolder ( configuredFolder ) ) {
188
210
try {
189
211
uri = URI . parse ( configuredFolder . uri ) ;
190
- if ( uri . path [ 0 ] !== '/' ) {
191
- uri = uri . with ( { path : '/' + uri . path } ) ; // this makes sure all workspace folder are absolute
212
+ if ( uri . path [ 0 ] !== posix . sep ) {
213
+ uri = uri . with ( { path : posix . sep + uri . path } ) ; // this makes sure all workspace folder are absolute
192
214
}
193
215
} catch ( e ) {
194
216
console . warn ( e ) ; // ignore
@@ -222,7 +244,6 @@ export function rewriteWorkspaceFileForNewLocation(rawWorkspaceContents: string,
222
244
const targetConfigFolder = extUri . dirname ( targetConfigPathURI ) ;
223
245
224
246
const rewrittenFolders : IStoredWorkspaceFolder [ ] = [ ] ;
225
- const slashForPath = useSlashForPath ( storedWorkspace . folders ) ;
226
247
227
248
for ( const folder of storedWorkspace . folders ) {
228
249
const folderURI = isRawFileWorkspaceFolder ( folder ) ? extUri . resolvePath ( sourceConfigFolder , folder . path ) : URI . parse ( folder . uri ) ;
@@ -232,7 +253,7 @@ export function rewriteWorkspaceFileForNewLocation(rawWorkspaceContents: string,
232
253
} else {
233
254
absolute = ! isRawFileWorkspaceFolder ( folder ) || isAbsolute ( folder . path ) ; // for existing workspaces, preserve whether a path was absolute or relative
234
255
}
235
- rewrittenFolders . push ( getStoredWorkspaceFolder ( folderURI , absolute , folder . name , targetConfigFolder , slashForPath , extUri ) ) ;
256
+ rewrittenFolders . push ( getStoredWorkspaceFolder ( folderURI , absolute , folder . name , targetConfigFolder , extUri ) ) ;
236
257
}
237
258
238
259
// Preserve as much of the existing workspace as possible by using jsonEdit
@@ -264,14 +285,6 @@ function doParseStoredWorkspace(path: URI, contents: string): IStoredWorkspace {
264
285
return storedWorkspace ;
265
286
}
266
287
267
- export function useSlashForPath ( storedFolders : IStoredWorkspaceFolder [ ] ) : boolean {
268
- if ( isWindows ) {
269
- return storedFolders . some ( folder => isRawFileWorkspaceFolder ( folder ) && folder . path . indexOf ( '/' ) >= 0 ) ;
270
- }
271
-
272
- return true ;
273
- }
274
-
275
288
//#endregion
276
289
277
290
//#region Workspace Storage
0 commit comments