Subversion Repository Public Repository

litesoft

Diff Revisions 905 vs 906 for /trunk/Java/core/Server/src/org/litesoft/util/TriDirUpdater.java

Diff revisions: vs.
  @@ -27,12 +27,18 @@
27 27 throws Exception
28 28 {
29 29 System.out.println( "3 (Tri) Directory Updater vs " + VERSION );
30 + String zEditor = System.getenv( "Editor" );
31 + if ( zEditor == null )
32 + {
33 + throw new IllegalStateException( "No 'Editor' environment variable" );
34 + }
30 35 if ( args.length != 3 )
31 36 {
32 37 showHelp();
33 38 }
34 39
35 - new TriDirUpdater( checkPath( "Update", args[0] ),
40 + new TriDirUpdater( zEditor,
41 + checkPath( "Update", args[0] ),
36 42 checkPath( "Original", args[1] ),
37 43 checkPath( "Working", args[2] ) ).process();
38 44 }
  @@ -77,11 +83,13 @@
77 83 System.exit( 1 );
78 84 }
79 85
86 + private final String mEditor;
80 87 private final File mUpdatePath;
81 88 private final TargetTree mOriginal, mWorking;
82 89
83 - private TriDirUpdater( File pUpdatePath, File pOriginalPath, File pWorkingPath )
90 + private TriDirUpdater( String pEditor, File pUpdatePath, File pOriginalPath, File pWorkingPath )
84 91 {
92 + mEditor = pEditor;
85 93 mUpdatePath = pUpdatePath;
86 94 mOriginal = new TargetTree( pOriginalPath );
87 95 mWorking = new TargetTree( pWorkingPath );
  @@ -112,7 +120,7 @@
112 120 File zFile = new File( mUpdatePath, zRelativePath );
113 121 if ( zFile.isFile() )
114 122 {
115 - processFile( zRelativePath );
123 + processUpdateFile( zRelativePath );
116 124 continue;
117 125 }
118 126 if ( zFile.isDirectory() )
  @@ -178,7 +186,7 @@
178 186 return mEntries.get( pRelativePath );
179 187 }
180 188
181 - public void remove( String pRelativePath )
189 + public void removeEntry( String pRelativePath )
182 190 {
183 191 mEntries.remove( pRelativePath );
184 192 }
  @@ -196,7 +204,7 @@
196 204 public void save( String pRelativePath, File pFile, byte[] pContents )
197 205 {
198 206 save( pFile, pContents );
199 - remove( pRelativePath );
207 + removeEntry( pRelativePath );
200 208 }
201 209
202 210 public void save( String pRelativePath, byte[] pContents )
  @@ -211,6 +219,11 @@
211 219 }
212 220 }
213 221
222 + private byte[] load( File pUpdateFile )
223 + {
224 + return FileUtils.load( pUpdateFile, MAX_FILE_SIZE );
225 + }
226 +
214 227 private boolean different( byte[] pBytes1, byte[] pBytes2 )
215 228 {
216 229 return !Arrays.equals( pBytes1, pBytes2 );
  @@ -221,57 +234,57 @@
221 234 // No 'Original' file...
222 235 // Same - No Action taken...
223 236 // Different...
224 - private void processFile( String pRelativePath )
237 + private void processUpdateFile( String pRelativePath )
225 238 {
226 239 File zUpdateFile = new File( mUpdatePath, pRelativePath );
227 - byte[] zUpdateContents = FileUtils.load( zUpdateFile, MAX_FILE_SIZE );
240 + byte[] zUpdateContents = load( zUpdateFile );
228 241 File zOriginalFile = mOriginal.getFile( pRelativePath );
229 242 if ( zOriginalFile == null )
230 243 {
231 - processNoOriginalFile( pRelativePath, zUpdateFile, zUpdateContents );
244 + processUpdateButNoOriginal( pRelativePath, zUpdateFile, zUpdateContents );
232 245 return;
233 246 }
234 - byte[] zOriginalContents = FileUtils.load( zOriginalFile, MAX_FILE_SIZE );
247 + byte[] zOriginalContents = load( zOriginalFile );
235 248 if ( different( zUpdateContents, zOriginalContents ) )
236 249 {
237 - processFilesDifferent( pRelativePath, zUpdateFile, zUpdateContents, zOriginalFile, zOriginalContents );
250 + processUpdateDifferentThanOriginal( pRelativePath, zUpdateFile, zUpdateContents, zOriginalFile, zOriginalContents );
238 251 return;
239 252 }
240 253 // Same!
241 - mOriginal.remove( pRelativePath );
242 - mWorking.remove( pRelativePath );
254 + mOriginal.removeEntry( pRelativePath );
255 + mWorking.removeEntry( pRelativePath );
243 256 }
244 257
245 - // Different:
258 + // No 'Update' file:
246 259 // a) 'Working' same as 'Original'
247 - // - Copy 'Update' to 'Working'.
260 + // - Delete 'Working'.
248 261 // b) 'Working' differs from 'Original'
249 - // - Offer 3-way Merge:
250 - // 'Update', 'Original', and 'Working'.
251 - // Copy 'Update' to 'Original'.
252 - private void processFilesDifferent( String pRelativePath, File pUpdateFile, byte[] pUpdateContents, File pOriginalFile, byte[] pOriginalContents )
262 + // - Offer Delete 'Working'?
263 + // (if 'Working' is 0 length, then delete).
264 + // Delete 'Original'.
265 + private void processNoUpdateFile( String pRelativePath )
253 266 {
254 267 File zWorkingFile = mWorking.getFile( pRelativePath );
255 - if ( zWorkingFile == null )
256 - {
257 - mWorking.save( pRelativePath, zWorkingFile, pUpdateContents );
258 - }
259 - else
268 + if ( zWorkingFile != null )
260 269 {
261 - byte[] zWorkingContents = FileUtils.load( zWorkingFile, MAX_FILE_SIZE );
262 - if ( !different( pOriginalContents, zWorkingContents ) )
263 - {
264 - mWorking.save( pRelativePath, zWorkingFile, pUpdateContents );
265 - }
266 - else if ( !threeWayMerge( pRelativePath, zWorkingFile, pOriginalFile, pUpdateFile ) )
270 + File zOriginalFile = mOriginal.getFile( pRelativePath );
271 + byte[] zWorkingContents = load( zWorkingFile );
272 + byte[] zOriginalContents = load( zOriginalFile );
273 + if ( different( zOriginalContents, zWorkingContents ) )
267 274 {
268 - // Ignore!
269 - mOriginal.remove( pRelativePath );
270 - mWorking.remove( pRelativePath );
271 - return;
275 + checkWorkingChangedButNoUpdate( pRelativePath, zWorkingFile, zOriginalFile );
276 + // ************************************* If Working is Empty, then complete merge!
277 + if ( zWorkingFile.length() != 0 )
278 + {
279 + // Ignore!
280 + mOriginal.removeEntry( pRelativePath );
281 + mWorking.removeEntry( pRelativePath );
282 + return;
283 + }
272 284 }
285 + mWorking.delete( pRelativePath );
273 286 }
274 - mOriginal.save( pRelativePath, pOriginalFile, pUpdateContents );
287 + mOriginal.delete( pRelativePath );
275 288 }
276 289
277 290 // No 'Original' file:
  @@ -280,113 +293,80 @@
280 293 // b) No 'Working' file
281 294 // - copy 'Update' to 'Working'.
282 295 // Copy 'Update' to 'Original'.
283 - private void processNoOriginalFile( String pRelativePath, File pUpdateFile, byte[] pUpdateContents )
296 + private void processUpdateButNoOriginal( String pRelativePath, File pUpdateFile, byte[] pUpdateContents )
284 297 {
285 298 File zWorkingFile = mWorking.getFile( pRelativePath );
286 299 if ( zWorkingFile != null )
287 300 {
288 - twoWayMerge( pRelativePath, zWorkingFile, pUpdateFile );
289 - mWorking.remove( pRelativePath );
290 - return;
301 + checkNewUpdateCollidesWithExistingWorking( pRelativePath, zWorkingFile, pUpdateFile );
302 + // ************************************* If Working is Empty, then complete merge!
303 + if ( zWorkingFile.length() != 0 )
304 + {
305 + // Ignore!
306 + mWorking.removeEntry( pRelativePath );
307 + return;
308 + }
291 309 }
292 310 mWorking.save( pRelativePath, pUpdateContents );
293 311 mOriginal.save( pRelativePath, pUpdateContents );
294 312 }
295 313
296 - // No 'Update' file:
314 + // Different:
297 315 // a) 'Working' same as 'Original'
298 - // - Delete 'Working'.
316 + // - Copy 'Update' to 'Working'.
299 317 // b) 'Working' differs from 'Original'
300 - // - Offer Delete 'Working'?
301 - // (if 'Working' is 0 length, then delete).
302 - // Delete 'Original'.
303 - private void processNoUpdateFile( String pRelativePath )
318 + // - Offer 3-way Merge:
319 + // 'Update', 'Original', and 'Working'.
320 + // Copy 'Update' to 'Original'.
321 + private void processUpdateDifferentThanOriginal( String pRelativePath, File pUpdateFile, byte[] pUpdateContents, File pOriginalFile,
322 + byte[] pOriginalContents )
304 323 {
305 324 File zWorkingFile = mWorking.getFile( pRelativePath );
306 325 if ( zWorkingFile == null )
307 326 {
308 - mOriginal.delete( pRelativePath );
309 - return;
327 + mWorking.save( pRelativePath, zWorkingFile, pUpdateContents );
310 328 }
311 - File zOriginalFile = mOriginal.getFile( pRelativePath );
312 - byte[] zOriginalContents = FileUtils.load( zOriginalFile, MAX_FILE_SIZE );
313 -
314 - byte[] zWorkingContents = FileUtils.load( zWorkingFile, MAX_FILE_SIZE );
315 - if ( different( zOriginalContents, zWorkingContents ) && !deleteNoUpdateButOriginalWithChangedWorking( pRelativePath ) )
329 + else
316 330 {
317 - // Ignore!
318 - mOriginal.remove( pRelativePath );
319 - mWorking.remove( pRelativePath );
320 - return;
331 + byte[] zWorkingContents = load( zWorkingFile );
332 + if ( !different( pOriginalContents, zWorkingContents ) )
333 + {
334 + mWorking.save( pRelativePath, zWorkingFile, pUpdateContents );
335 + }
336 + else
337 + {
338 + checkUpdateAndWorkingDifferentThanOriginal_threeWayMerge( pRelativePath, zWorkingFile, pUpdateFile, pOriginalFile );
339 + // ************************************* If Working changed, then complete merge!
340 + if ( !different( zWorkingContents, load( zWorkingFile ) ) )
341 + {
342 + // Ignore!
343 + mOriginal.removeEntry( pRelativePath );
344 + mWorking.removeEntry( pRelativePath );
345 + return;
346 + }
347 + }
321 348 }
322 - mWorking.delete( pRelativePath );
323 - mOriginal.delete( pRelativePath );
349 + mOriginal.save( pRelativePath, pOriginalFile, pUpdateContents );
350 + }
351 +
352 + private void checkWorkingChangedButNoUpdate( String pRelativePath, File pWorkingFile, File pOriginalFile )
353 + {
354 + System.out.println( "Working Changed But No Update: " + pRelativePath + "\n" +
355 + " So Working shouldn't exist - Empty Working to complete merge..." );
356 + ShellUtils.shell( mEditor, pWorkingFile.getAbsolutePath(), pOriginalFile.getAbsolutePath() );
324 357 }
325 358
326 - // /**
327 - // * Move Dir - Assume same volume!
328 - // */
329 - // @Override
330 - // protected boolean moveDir( File pSource, File pDestination )
331 - // {
332 - // Directories.deleteIfExists( pDestination );
333 - // Directories.moveFile( pSource, pDestination );
334 - // return true;
335 - // }
336 - //
337 - // /**
338 - // * Move File - Assume same volume!
339 - // */
340 - // @Override
341 - // protected boolean moveFile( File pSource, File pDestination )
342 - // {
343 - // FileUtils.deleteIfExists( pDestination );
344 - // Directories.moveFile( pSource, pDestination );
345 - // return true;
346 - // }
347 - //
348 - // /**
349 - // * Update the existing pDestination from the pSource - Assume NOT the same volume!
350 - // */
351 - // @Override
352 - // protected boolean updateFile( File pSource, File pDestination )
353 - // {
354 - // byte[] srcBytes = FileUtils.load( pSource, MAX_FILE_SIZE );
355 - // byte[] dstBytes = FileUtils.load( pDestination, MAX_FILE_SIZE );
356 - // if ( !Bytes.areArraysEqual( srcBytes, dstBytes ) )
357 - // {
358 - // FileUtils.deleteIfExists( pDestination );
359 - // FileUtils.store( pDestination, srcBytes );
360 - // return true;
361 - // }
362 - // return false;
363 - // }
364 - //
365 - // /**
366 - // * Copy the pSource to the pDestination - Assume NOT the same volume!
367 - // */
368 - // @Override
369 - // protected boolean copyAddFile( File pSource, File pDestination )
370 - // {
371 - // byte[] zBytes = FileUtils.load( pSource, MAX_FILE_SIZE );
372 - // FileUtils.store( pDestination, zBytes );
373 - // return true;
374 - // }
375 -
376 - private void twoWayMerge( String pRelativePath, File pWorkingFile, File pUpdateFile )
377 - {
378 - System.out.println( "twoWayMerge Working & Update: " + pRelativePath ); // TODO: XXX
379 - }
380 -
381 - private boolean threeWayMerge( String pRelativePath, File pWorkingFile, File pOriginalFile, File pUpdateFile )
359 + private void checkNewUpdateCollidesWithExistingWorking( String pRelativePath, File pWorkingFile, File pUpdateFile )
382 360 {
383 - System.out.println( "threeWayMerge: " + pRelativePath );
384 - return false; // TODO: XXX
361 + System.out.println( "New Update Collides With Existing Working: " + pRelativePath + "\n" +
362 + " Move contents of Working to new file (leaving Working empty) to complete merge..." );
363 + ShellUtils.shell( mEditor, pWorkingFile.getAbsolutePath(), pUpdateFile.getAbsolutePath() );
385 364 }
386 365
387 - private boolean deleteNoUpdateButOriginalWithChangedWorking( String pRelativePath )
366 + private void checkUpdateAndWorkingDifferentThanOriginal_threeWayMerge( String pRelativePath, File pWorkingFile, File pUpdateFile, File pOriginalFile )
388 367 {
389 - System.out.println( "deleteNoUpdateButOriginalWithChangedWorking: " + pRelativePath );
390 - return false; // TODO: XXX
368 + System.out.println( "Change Collition, both Update AND Working differ from Original: " + pRelativePath + "\n" +
369 + " Change Working to complete merge..." );
370 + ShellUtils.shell( mEditor, pWorkingFile.getAbsolutePath(), pUpdateFile.getAbsolutePath(), pOriginalFile.getAbsolutePath() );
391 371 }
392 372 }