2403 |
2402 |
2404 "Created: 15.10.1996 / 11:13:00 / cg" |
2403 "Created: 15.10.1996 / 11:13:00 / cg" |
2405 "Modified: 22.3.1997 / 16:12:17 / cg" |
2404 "Modified: 22.3.1997 / 16:12:17 / cg" |
2406 ! |
2405 ! |
2407 |
2406 |
2408 fileOutAs:fileNameString |
2407 fileOutAs:filenameString |
2409 "create a file consisting of all methods in myself in |
2408 "create a file consisting of all methods in myself in |
2410 sourceForm, from which the class can be reconstructed (by filing in). |
2409 sourceForm, from which the class can be reconstructed (by filing in). |
2411 The given fileName should be a full path, including suffix. |
2410 The given fileName should be a full path, including suffix. |
2412 Care is taken, to not clobber any existing file in |
2411 Care is taken, to not clobber any existing file in |
2413 case of errors (for example: disk full). |
2412 case of errors (for example: disk full). |
2414 Also, since the classes methods need a valid sourcefile, the current |
2413 Also, since the classes methods need a valid sourcefile, the current |
2415 sourceFile may not be rewritten." |
2414 sourceFile may not be rewritten." |
2416 |
2415 |
2417 |aStream fileName newFileName savFilename needRename |
2416 |filename fileExists needRename |
2418 mySourceFileName sameFile s mySourceFileID anySourceRef| |
2417 mySourceFileName sameFile s mySourceFileID anySourceRef outStream savFilename| |
2419 |
2418 |
2420 self isLoaded ifFalse:[ |
2419 self isLoaded ifFalse:[ |
2421 ^ FileOutErrorSignal |
2420 ^ FileOutErrorSignal |
2422 raiseRequestWith:self |
2421 raiseRequestWith:self |
2423 errorString:' - will not fileOut unloaded class: ', self name |
2422 errorString:' - will not fileOut unloaded class: ', self name |
2424 ]. |
2423 ]. |
2425 |
2424 |
2426 fileName := fileNameString asFilename. |
2425 filename := filenameString asFilename. |
2427 |
2426 |
2428 " |
2427 " |
2429 if file exists, copy the existing to a .sav-file, |
2428 if file exists, copy the existing to a .sav-file, |
2430 create the new file as XXX.new-file, |
2429 create the new file as XXX.new-file, |
2431 and, if that worked rename afterwards ... |
2430 and, if that worked rename afterwards ... |
2432 " |
2431 " |
2433 (fileName exists) ifTrue:[ |
2432 [ |
2434 sameFile := false. |
2433 fileExists := filename exists. |
2435 |
2434 fileExists ifTrue:[ |
2436 "/ check carefully - maybe, my source does not really come from that |
2435 sameFile := false. |
2437 "/ file (i.e. all of my methods have their source as string) |
2436 |
2438 |
2437 "/ check carefully - maybe, my source does not really come from that |
2439 anySourceRef := false. |
2438 "/ file (i.e. all of my methods have their source as string) |
2440 self instAndClassMethodsDo:[:m | |
2439 |
2441 m sourcePosition notNil ifTrue:[ |
2440 anySourceRef := false. |
2442 anySourceRef := true |
2441 self instAndClassMethodsDo:[:m | |
|
2442 m sourcePosition notNil ifTrue:[ |
|
2443 anySourceRef := true |
|
2444 ] |
|
2445 ]. |
|
2446 |
|
2447 anySourceRef ifTrue:[ |
|
2448 s := self sourceStream. |
|
2449 s notNil ifTrue:[ |
|
2450 OperatingSystem isUNIXlike ifTrue:[ |
|
2451 mySourceFileID := s pathName asFilename info id. |
|
2452 sameFile := (filename info id) == mySourceFileID. |
|
2453 ] ifFalse:[ |
|
2454 mySourceFileID := s pathName asFilename asAbsoluteFilename. |
|
2455 sameFile := (filename asFilename asAbsoluteFilename) = mySourceFileID. |
|
2456 ]. |
|
2457 s close. |
|
2458 ] ifFalse:[ |
|
2459 classFilename notNil ifTrue:[ |
|
2460 " |
|
2461 check for overwriting my current source file |
|
2462 this is not allowed, since it would clobber my methods source |
|
2463 file ... you have to save it to some other place. |
|
2464 This happens if you ask for a fileOut into the source-directory |
|
2465 (from which my methods get their source) |
|
2466 " |
|
2467 mySourceFileName := Smalltalk getSourceFileName:classFilename. |
|
2468 sameFile := (filenameString = mySourceFileName). |
|
2469 sameFile ifFalse:[ |
|
2470 mySourceFileName notNil ifTrue:[ |
|
2471 OperatingSystem isUNIXlike ifTrue:[ |
|
2472 sameFile := (filename info id) == (mySourceFileName asFilename info id) |
|
2473 ] |
|
2474 ] |
|
2475 ]. |
|
2476 ] |
|
2477 ]. |
|
2478 ]. |
|
2479 |
|
2480 sameFile ifTrue:[ |
|
2481 ^ FileOutErrorSignal |
|
2482 raiseRequestWith:filenameString |
|
2483 errorString:(' - may not overwrite sourcefile: %1\try again after loading sources in the browser' withCRs bindWith:filenameString) |
|
2484 ]. |
|
2485 |
|
2486 outStream := FileStream newTemporaryIn:filename directory. |
|
2487 outStream fileName accessRights:filename accessRights. |
|
2488 needRename := true |
|
2489 ] ifFalse:[ |
|
2490 "/ another possible trap: if my sourceFileName is |
|
2491 "/ the same as the written one AND the new files directory |
|
2492 "/ is along the sourcePath, we also need a temporary file |
|
2493 "/ first, to avoid accessing the newly written file. |
|
2494 |
|
2495 self instAndClassMethodsDo:[:m | |
|
2496 |mSrc mSrcFilename| |
|
2497 |
|
2498 (anySourceRef isNil and:[(mSrc := m sourceFilename) notNil]) ifTrue:[ |
|
2499 mSrcFilename := mSrc asFilename. |
|
2500 (mSrcFilename baseName = filename baseName |
|
2501 and:[mSrcFilename exists]) ifTrue:[ |
|
2502 anySourceRef := mSrcFilename. |
|
2503 ] |
|
2504 ] |
|
2505 ]. |
|
2506 anySourceRef notNil ifTrue:[ |
|
2507 outStream := FileStream newTemporaryIn:filename directory. |
|
2508 outStream fileName accessRights:anySourceRef accessRights. |
|
2509 needRename := true |
|
2510 ] ifFalse:[ |
|
2511 outStream := filename writeStream. |
|
2512 needRename := false |
2443 ] |
2513 ] |
2444 ]. |
2514 ]. |
2445 |
|
2446 anySourceRef ifTrue:[ |
|
2447 s := self sourceStream. |
|
2448 s notNil ifTrue:[ |
|
2449 OperatingSystem isUNIXlike ifTrue:[ |
|
2450 mySourceFileID := s pathName asFilename info id. |
|
2451 sameFile := (fileName info id) == mySourceFileID. |
|
2452 ] ifFalse:[ |
|
2453 mySourceFileID := s pathName asFilename asAbsoluteFilename. |
|
2454 sameFile := (fileName asFilename asAbsoluteFilename) = mySourceFileID. |
|
2455 ]. |
|
2456 s close. |
|
2457 ] ifFalse:[ |
|
2458 classFilename notNil ifTrue:[ |
|
2459 " |
|
2460 check for overwriting my current source file |
|
2461 this is not allowed, since it would clobber my methods source |
|
2462 file ... you have to save it to some other place. |
|
2463 This happens if you ask for a fileOut into the source-directory |
|
2464 (from which my methods get their source) |
|
2465 " |
|
2466 mySourceFileName := Smalltalk getSourceFileName:classFilename. |
|
2467 sameFile := (fileNameString = mySourceFileName). |
|
2468 sameFile ifFalse:[ |
|
2469 mySourceFileName notNil ifTrue:[ |
|
2470 OperatingSystem isUNIXlike ifTrue:[ |
|
2471 sameFile := (fileName info id) == (mySourceFileName asFilename info id) |
|
2472 ] |
|
2473 ] |
|
2474 ]. |
|
2475 ] |
|
2476 ]. |
|
2477 ]. |
|
2478 |
|
2479 sameFile ifTrue:[ |
|
2480 ^ FileOutErrorSignal |
|
2481 raiseRequestWith:fileNameString |
|
2482 errorString:(' - may not overwrite sourcefile: %1\try again after loading sources in the browser' withCRs bindWith:fileNameString) |
|
2483 ]. |
|
2484 |
|
2485 savFilename := Filename newTemporary. |
|
2486 fileName copyTo:savFilename. |
|
2487 newFileName := fileName withSuffix:'new'. |
|
2488 needRename := true |
|
2489 ] ifFalse:[ |
|
2490 "/ another possible trap: if my sourceFileName is |
|
2491 "/ the same as the written one AND the new files directory |
|
2492 "/ is along the sourcePath, we also need a temporary file |
|
2493 "/ first, to avoid accessing the newly written file. |
|
2494 |
|
2495 anySourceRef := false. |
|
2496 self instAndClassMethodsDo:[:m | |
|
2497 |mSrc| |
|
2498 |
|
2499 (mSrc := m sourceFilename) notNil ifTrue:[ |
|
2500 mSrc asFilename baseName = fileName baseName ifTrue:[ |
|
2501 anySourceRef := true |
|
2502 ] |
|
2503 ] |
|
2504 ]. |
|
2505 anySourceRef ifTrue:[ |
|
2506 newFileName := fileName withSuffix:'new'. |
|
2507 needRename := true |
|
2508 ] ifFalse:[ |
|
2509 newFileName := fileName. |
|
2510 needRename := false |
|
2511 ] |
|
2512 ]. |
|
2513 [ |
|
2514 aStream := newFileName writeStream. |
|
2515 ] on:FileStream openErrorSignal do:[:ex| |
2515 ] on:FileStream openErrorSignal do:[:ex| |
2516 savFilename notNil ifTrue:[ |
|
2517 savFilename delete |
|
2518 ]. |
|
2519 ^ FileOutErrorSignal |
2516 ^ FileOutErrorSignal |
2520 raiseRequestWith:newFileName name |
2517 raiseRequestWith:filename name |
2521 errorString:(' - cannot create file:', newFileName name) |
2518 errorString:(' - cannot create file:', filename name) |
2522 ]. |
2519 ]. |
2523 self fileOutOn:aStream. |
2520 self fileOutOn:outStream. |
2524 aStream close. |
2521 outStream syncData; close. |
2525 |
2522 |
2526 " |
2523 " |
2527 finally, replace the old-file |
2524 finally, replace the old-file |
2528 be careful, if the old one is a symbolic link; in this case, |
2525 be careful, if the old one is a symbolic link; in this case, |
2529 we have to do a copy ... |
2526 we have to do a copy ... |
2530 " |
2527 " |
2531 needRename ifTrue:[ |
2528 needRename ifTrue:[ |
2532 newFileName copyTo:fileName. |
2529 fileExists ifTrue:[ |
2533 newFileName delete |
2530 savFilename := filename addSuffix:'.sav~'. |
2534 ]. |
2531 savFilename delete. |
2535 savFilename notNil ifTrue:[ |
2532 filename renameTo:savFilename. |
2536 savFilename delete |
2533 ]. |
|
2534 outStream fileName renameTo:filename. |
|
2535 fileExists ifTrue:[ |
|
2536 savFilename delete. |
|
2537 ]. |
2537 ]. |
2538 ]. |
2538 |
2539 |
2539 " |
2540 " |
2540 add a change record; that way, administration is much easier, |
2541 add a change record; that way, administration is much easier, |
2541 since we can see in that changeBrowser, which changes have |
2542 since we can see in that changeBrowser, which changes have |