@@ -8,7 +8,10 @@ import {
88 documentContentProvider ,
99 FILESYSTEM_SCHEMA ,
1010 FILESYSTEM_READONLY_SCHEMA ,
11+ OBJECTSCRIPT_FILE_SCHEMA ,
1112 fileSystemProvider ,
13+ workspaceState ,
14+ schemas ,
1215} from "../extension" ;
1316import { DocumentContentProvider } from "../providers/DocumentContentProvider" ;
1417import { currentFile , CurrentFile , outputChannel } from "../utils" ;
@@ -25,18 +28,91 @@ async function compileFlags(): Promise<string> {
2528 } ) ;
2629}
2730
28- async function importFile ( file : CurrentFile ) : Promise < any > {
31+ export async function checkChangedOnServer ( file : CurrentFile ) : Promise < number > {
32+ if ( ! file || ! file . uri || schemas . includes ( file . uri . scheme ) ) {
33+ return - 1 ;
34+ }
35+ const api = new AtelierAPI ( file . uri ) ;
36+ const mtime =
37+ workspaceState . get ( `${ file . uniqueId } :mtime` , null ) ||
38+ ( await api
39+ . getDoc ( file . name )
40+ . then ( ( data ) => data . result )
41+ . then ( ( { ts, content } ) => {
42+ const fileContent = file . content . split ( / \r ? \n / ) ;
43+ const serverTime = Number ( new Date ( ts + "Z" ) ) ;
44+ const sameContent = content . every ( ( line , index ) => line . trim ( ) == ( fileContent [ index ] || "" ) . trim ( ) ) ;
45+ const mtime = sameContent ? serverTime : Math . max ( Number ( fs . statSync ( file . fileName ) . mtime ) , serverTime ) ;
46+ return mtime ;
47+ } )
48+ . catch ( ( ) => - 1 ) ) ;
49+ workspaceState . update ( `${ file . uniqueId } :mtime` , mtime > 0 ? mtime : undefined ) ;
50+ return mtime ;
51+ }
52+
53+ async function importFile ( file : CurrentFile , ignoreConflict ?: boolean ) : Promise < any > {
2954 const api = new AtelierAPI ( file . uri ) ;
55+ const content = file . content . split ( / \r ? \n / ) ;
56+ const mtime = await checkChangedOnServer ( file ) ;
57+ ignoreConflict = ignoreConflict || mtime < 0 ;
3058 return api
3159 . putDoc (
3260 file . name ,
3361 {
34- content : file . content . split ( / \r ? \n / ) ,
62+ content,
3563 enc : false ,
64+ mtime,
3665 } ,
37- true
66+ ignoreConflict
3867 )
39- . catch ( ( error ) => vscode . window . showErrorMessage ( error . message ) ) ;
68+ . catch ( ( error ) => {
69+ if ( error . statusCode == 400 ) {
70+ outputChannel . appendLine ( error . error . result . status ) ;
71+ vscode . window . showErrorMessage ( error . error . result . status ) ;
72+ return Promise . reject ( ) ;
73+ }
74+ if ( error . statusCode == 409 ) {
75+ return vscode . window
76+ . showErrorMessage (
77+ `Failed to import '${ file . name } ': The version of the file on the server is newer.
78+ What do you want to do?` ,
79+ "Compare" ,
80+ "Overwrite on Server" ,
81+ "Pull Server Changes" ,
82+ "Cancel"
83+ )
84+ . then ( ( action ) => {
85+ switch ( action ) {
86+ case "Compare" :
87+ return vscode . commands
88+ . executeCommand (
89+ "vscode.diff" ,
90+ file . uri ,
91+ vscode . Uri . file ( file . name ) . with ( {
92+ scheme : OBJECTSCRIPT_FILE_SCHEMA ,
93+ authority : file . workspaceFolder ,
94+ } ) ,
95+ `Local • ${ file . fileName } ↔ Server • ${ file . name } `
96+ )
97+ . then ( ( ) => Promise . reject ( ) ) ;
98+ case "Overwrite on Server" :
99+ return importFile ( file , true ) ;
100+ case "Pull Server Changes" :
101+ outputChannel . appendLine ( `${ file . name } : Loading changes from server` ) ;
102+ outputChannel . show ( true ) ;
103+ loadChanges ( [ file ] ) ;
104+ return Promise . reject ( ) ;
105+ case "Cancel" :
106+ outputChannel . appendLine ( `${ file . name } : Import and Compile canceled by user` ) ;
107+ outputChannel . show ( true ) ;
108+ return Promise . reject ( ) ;
109+ }
110+ return Promise . reject ( ) ;
111+ } ) ;
112+ }
113+ vscode . window . showErrorMessage ( error . message ) ;
114+ return Promise . reject ( ) ;
115+ } ) ;
40116}
41117
42118function updateOthers ( others : string [ ] ) {
@@ -57,6 +133,8 @@ export async function loadChanges(files: CurrentFile[]): Promise<any> {
57133 . getDoc ( file . name )
58134 . then ( ( data ) => {
59135 const content = ( data . result . content || [ ] ) . join ( file . eol === vscode . EndOfLine . LF ? "\n" : "\r\n" ) ;
136+ const mtime = Number ( new Date ( data . result . ts + "Z" ) ) ;
137+ workspaceState . update ( `${ file . uniqueId } :mtime` , mtime > 0 ? mtime : undefined ) ;
60138 if ( file . uri . scheme === "file" ) {
61139 fs . writeFileSync ( file . fileName , content ) ;
62140 } else if ( file . uri . scheme === FILESYSTEM_SCHEMA || file . uri . scheme === FILESYSTEM_READONLY_SCHEMA ) {
0 commit comments