FileOperation.st
author Claus Gittinger <cg@exept.de>
Tue, 03 Aug 2004 12:05:12 +0200
changeset 5961 f91c25cf2475
parent 5888 f2758e87cb4f
child 6011 a1ec5a37039e
permissions -rw-r--r--
private classes are private

"{ Package: 'stx:libtool2' }"

Object subclass:#FileOperation
	instanceVariableNames:'errorString result'
	classVariableNames:''
	poolDictionaries:''
	category:'Interface-Support'
!

FileOperation subclass:#Copy
	instanceVariableNames:'colOfCopiedFiles'
	classVariableNames:''
	poolDictionaries:''
	privateIn:FileOperation
!

FileOperation subclass:#Create
	instanceVariableNames:'createdFile'
	classVariableNames:'LastCreatedDirectory LastCreatedFile'
	poolDictionaries:''
	privateIn:FileOperation
!

FileOperation subclass:#Delete
	instanceVariableNames:'fileName'
	classVariableNames:''
	poolDictionaries:''
	privateIn:FileOperation
!

FileOperation subclass:#Move
	instanceVariableNames:'colOfMovedFiles'
	classVariableNames:''
	poolDictionaries:''
	privateIn:FileOperation
!

FileOperation subclass:#Rename
	instanceVariableNames:'renamedFiles'
	classVariableNames:''
	poolDictionaries:''
	privateIn:FileOperation
!


!FileOperation class methodsFor:'actions'!

copyFile:aSourceFile to:aDestFile withOverWriteWarning:overWriteWarningBoolean copyFileIfSame:copyIfSameBoolean
    ^ Copy 
        copyFile:aSourceFile to:aDestFile 
        withOverWriteWarning:overWriteWarningBoolean 
        copyFileIfSame:copyIfSameBoolean
!

copyFiles:aColOfSourceFiles to:aDirectory
    ^ Copy copyFiles:aColOfSourceFiles to:aDirectory
!

createDirectoryIn:aDirectory
    ^ Create createDirectoryIn:aDirectory
!

createDirectoryIn:aDirectory initialAnswer:defaultAnswer
    ^ Create createDirectoryIn:aDirectory initialAnswer:defaultAnswer
!

createFileIn:aDirectory
    ^ Create createFileIn:aDirectory
!

createHardLinkIn:dir
    ^ Create createHardLinkIn:dir
!

createSoftLinkIn:dir
    ^ Create createSoftLinkIn:dir
!

deleteFiles:colOfFiles confirm:confirm
    ^ Delete deleteFiles:colOfFiles confirm:confirm
!

moveFile:aSourceFile to:aDestFile
    ^ Move 
        moveFile:aSourceFile to:aDestFile
!

moveFiles:aCollectionOfFiles to:aDestDirectory
    ^ Move 
        moveFiles:aCollectionOfFiles to:aDestDirectory
!

renameFile:filename to:newFileString
    ^ Rename 
        renameFile:filename to:newFileString
!

renameFiles:aCollectionofFilenames
    ^ Rename 
        renameFiles:aCollectionofFilenames
! !

!FileOperation class methodsFor:'defaults'!

copyMoveIfExistSuffixString

    ^ '.copy'
! !

!FileOperation methodsFor:'accessing'!

errorString
    "return the value of the static variable 'ErrorString' (automatically generated)"

    ^ errorString
!

errorString:something
    "set the value of the static variable 'ErrorString' (automatically generated)"

    errorString := something.
!

result
    "return the value of the instance variable 'result' (automatically generated)"

    ^ result
!

result:something
    "set the value of the instance variable 'result' (automatically generated)"

    result := something.
! !

!FileOperation methodsFor:'dialogs'!

fileExistDialogForNewFile:newFile oldFile:oldFile withCancel:withCancel
    "return true, if the file should be moved/copied.
     Ask user if oldFile exists."

    ^ self fileExistDialogForNewFile:newFile oldFile:oldFile withCancel:withCancel withRemoveIfSame:false.
!

fileExistDialogForNewFile:newFile oldFile:oldFile withCancel:withCancel withRemoveIfSame:withRemoveIfSame
    "return true, if the file should be moved/copied.
     If oldFile exists, ask user.
     If withRemoveIfSame is true, two additional possible values are returned:
        #removeSource and #removeDestination.
    "

    |msg oldSize newSize sameContents resources sourceType destType|

    newFile exists ifFalse:[ ^ true ].
    oldSize := oldFile fileSize.
    newSize := newFile fileSize.

    sameContents := false.

    newFile isDirectory ifTrue:[
        oldFile isDirectory ifTrue:[
            "/ could (should?) recursively look for same contents here...
        ].
    ] ifFalse:[
        oldFile isDirectory ifFalse:[
            sameContents := oldSize = newSize and:[oldFile sameContentsAs:newFile].
        ]
    ].

    "/ for now:
    oldFile isDirectory ~~ newFile isDirectory ifTrue:[
        Dialog warn:(resources string:'Will not overwrite directory with file and vice versa.').
        ^  false.
    ].

    sourceType := newFile isDirectory ifTrue:'directory' ifFalse:'file'.
    destType := oldFile isDirectory ifTrue:'directory' ifFalse:'file'.

    sameContents ifTrue:[
        msg := 'Overwrite existing destination %7:\\  %1\    size: %3 of %2\\with source (same contents):\\  %4\    size: %6 of %5'.
    ] ifFalse:[
        msg := 'Overwrite existing destination %7:\\  %1\    size: %3 of %2\\with source:\\  %4\    size: %6 of %5'.
    ].

    resources := AbstractFileBrowser classResources.
    msg := resources 
            stringWithCRs:msg
            withArgs:(Array
                with:newFile asString allBold
                with:(newFile modificationTime printStringFormat:'%(Day)-%(mon)-%(year) %h:%m:%s')
                with:newSize
                with:oldFile asString allBold 
                with:(oldFile modificationTime printStringFormat:'%(Day)-%(mon)-%(year) %h:%m:%s')
                with:oldSize
                with:destType).

    (sameContents and:[withRemoveIfSame]) ifTrue:[
        ^ OptionBox  
                  request:msg
                  label:(resources string:'Overwrite existing file')
                  image:(YesNoBox iconBitmap)
                  buttonLabels:(resources array:( #('No' 'Remove Source' 'Remove Destination' 'Yes' ) , (withCancel ifTrue:[#('Cancel')] ifFalse:[#()])))
                  values:#( false #removeSource #removeDestination true )
                  default:#removeSource
                  onCancel:nil.
    ] ifFalse:[
        ^ Dialog confirm:msg withCancel:withCancel.
    ].
! !

!FileOperation::Copy class methodsFor:'actions'!

copyFile:aSourceFile to:aDestFile
    "delete current selected files/directories
    "

    |instance|

    instance := self new.
    instance copyFile:aSourceFile to:aDestFile.
    ^ instance
!

copyFile:aSourceFile to:aDestFile withOverWriteWarning:overWriteWarning
    "delete current selected files/directories
    "

    |instance|

    instance := self new.
    instance copyFile:aSourceFile to:aDestFile withOverWriteWarning:overWriteWarning.
    ^ instance
!

copyFile:aSourceFile to:aDestFile withOverWriteWarning:overWriteWarningBoolean copyFileIfSame:copyIfSameBoolean
    "delete current selected files/directories
    "

    |instance|

    instance := self new.
    instance copyFile:aSourceFile to:aDestFile withOverWriteWarning:overWriteWarningBoolean copyFileIfSame:copyIfSameBoolean.
    ^ instance
!

copyFiles:aColOfSourceFiles to:aDirectory
    "delete current selected files/directories
    "

    |instance|

    instance := self new.
    instance copyFiles:aColOfSourceFiles to:aDirectory.
    ^ instance
!

copyFiles:aColOfSourceFiles to:aDirectory withOverWriteWarning:overWriteWarning
    "delete current selected files/directories
    "

    |instance|

    instance := self new.
    instance copyFiles:aColOfSourceFiles to:aDirectory withOverWriteWarning:overWriteWarning.
    ^ instance
!

copyFiles:aColOfSourceFiles to:aDirectory withOverWriteWarning:overWriteWarning copyFileIfSame:copy
    "delete current selected files/directories
    "

    |instance|

    instance := self new.
    instance copyFiles:aColOfSourceFiles to:aDirectory withOverWriteWarning:overWriteWarning copyFileIfSame:copy.
    ^ instance
! !

!FileOperation::Copy class methodsFor:'documentation'!

version
    ^ '$Header: /cvs/stx/stx/libtool/FileOperation.st,v 1.55 2004-08-03 10:04:44 cg Exp $'
! !

!FileOperation::Copy methodsFor:'accessing'!

colOfCopiedFiles
    "return the value of the instance variable 'colOfCopiedFiles' (automatically generated)"

    colOfCopiedFiles isNil ifTrue:[
        colOfCopiedFiles := OrderedCollection new.
    ].
    ^ colOfCopiedFiles
! !

!FileOperation::Copy methodsFor:'actions'!

copyFile:aSourceFile to:aDestFile
    "defete current selected files/directories
    "

    self copyFile:aSourceFile to:aDestFile withOverWriteWarning:true
!

copyFile:aSourceFile to:aDestFile withOverWriteWarning:overWriteWarning
    "copy to
    "

    self copyFile:aSourceFile to:aDestFile withOverWriteWarning:true copyFileIfSame:true
!

copyFile:aSourceFile to:aDestFile withOverWriteWarning:overWriteWarningBoolean copyFileIfSame:copyIfSameBoolean
    "copy to
    "

    |newFile fileString targetDirectory targetIsDirectory sourceIsDirectory suffix|

    sourceIsDirectory := aSourceFile isDirectory.
    targetIsDirectory := aDestFile isDirectory.
    targetIsDirectory ifTrue:[
        targetDirectory := aDestFile.
        newFile := aDestFile construct:(aSourceFile baseName).
    ] ifFalse:[
        targetDirectory := aDestFile directory.
        newFile := aDestFile.
    ].
    "/ do not copy if destination directory doest exist.
    (targetDirectory exists not) ifTrue:[
        Dialog warn:'cant copy to not existing directory ', targetDirectory asString. 
        result := false.
        ^ self
    ].
    (newFile exists) ifTrue:[
        ((newFile asString = aSourceFile asString) and:[copyIfSameBoolean]) ifTrue:[
            [newFile exists] whileTrue:[
                suffix := newFile suffix.
                fileString := newFile baseName withoutSuffix, self class copyMoveIfExistSuffixString, '.', suffix.
                newFile := targetDirectory construct:fileString.
            ].
        ] ifFalse:[
            overWriteWarningBoolean ifTrue:[
                (self fileExistDialogForNewFile:newFile oldFile:aSourceFile withCancel:false withRemoveIfSame:false) ifFalse:[ 
                    result := false.
                    ^ self.
                ]
            ] ifFalse:[
                    result := false.
                    ^ self.
            ]
        ].
    ].
    Error handle:[:ex|
        "was not able to copy it"
        WarningBox warn:'on copy file - ', ex errorString.
        self errorString:('on copy file - ', ex description asString).
        result := false.
        ^ self
    ] do:[
        sourceIsDirectory ifTrue:[
            OperatingSystem recursiveCopyDirectory:(aSourceFile pathName) to:(newFile pathName).
        ] ifFalse:[
            aSourceFile copyTo:newFile.
        ].
    ].
    DirectoryContents flushCachedDirectoryFor:(aSourceFile directory).
    result := true.
!

copyFiles:aColOfSourceFiles to:aDirectory

    ^ self copyFiles:aColOfSourceFiles to:aDirectory withOverWriteWarning:true. 
!

copyFiles:aColOfSourceFiles to:aDirectory withOverWriteWarning:overWriteWarning 

    ^ self copyFiles:aColOfSourceFiles to:aDirectory withOverWriteWarning:overWriteWarning copyFileIfSame:true.
!

copyFiles:aColOfSourceFiles to:aDirectory withOverWriteWarning:overWriteWarning copyFileIfSame:copy


    |newFile suffix fileString sourceIsDirectory overWriteExisting|

    (aDirectory exists not) ifTrue:[
        Dialog warn:'cant copy to not existing directory ', aDirectory asString. 
        result := false.
        ^ self
    ].
    (aDirectory isDirectory not) ifTrue:[
        Dialog warn:'destination ', aDirectory asString, ' is not a directory'. 
        result := false.
        ^ self
    ].
    aColOfSourceFiles do:[: filename |
        newFile := aDirectory construct:(filename baseName).
        sourceIsDirectory := filename isDirectory.
        overWriteExisting := true.
        (newFile exists) ifTrue:[
            ((newFile asString = filename asString) and:[copy]) ifTrue:[
                [newFile exists] whileTrue:[
                    suffix := newFile suffix.
                    fileString := newFile withoutSuffix baseName, self class copyMoveIfExistSuffixString.
                    suffix notEmpty ifTrue:[
                        fileString := fileString, '.', suffix.
                    ].
                    newFile := aDirectory construct:fileString.
                ].
            ] ifFalse:[
                overWriteWarning ifTrue:[
                    overWriteExisting := (self fileExistDialogForNewFile:newFile oldFile:filename withCancel:(aColOfSourceFiles size > 1) withRemoveIfSame:false).
                    overWriteExisting isNil ifTrue:[
                        " abort pressed "
                        result := false.
                        ^ self.
                    ]
                ]
            ].
        ].
        overWriteExisting ifTrue:[
            Error handle:[:ex|
                "was not able to copy it"
                result := false.
                self errorString:('on copy file - ', ex description asString).
                ( Dialog 
                    confirm:('error on copy file - ', ex description asString) 
                    title:'Copy'
                    yesLabel:'Continue' 
                    noLabel:'Abort') ifTrue:[
                        ex proceed.
                    ] ifFalse:[
                        ^ self.
                    ].
            ] do:[
                sourceIsDirectory ifTrue:[
                    OperatingSystem recursiveCopyDirectory:(filename asString)  
                                                        to:(newFile asString).
                ] ifFalse:[
                    filename copyTo:newFile.
                ].
            ].
            self colOfCopiedFiles add:filename
        ]
    ].
    DirectoryContents flushCachedDirectoryFor:aDirectory.
    result := true.
! !

!FileOperation::Create class methodsFor:'actions'!

createDirectoryIn:aDirectory

    |instance|

    instance := self new.
    instance createDirectoryIn:aDirectory.
    ^ instance
!

createDirectoryIn:aDirectory initialAnswer:defaultAnswer

    |instance|

    instance := self new.
    instance createDirectoryIn:aDirectory initialAnswer:defaultAnswer.
    ^ instance
!

createFileIn:aFile

    |instance|

    instance := self new.
    instance createFileIn:aFile.
    ^ instance
!

createHardLinkIn:aFile
    "create an new hard link in a files directory"

    |instance|

    instance := self new.
    instance createHardLinkIn:aFile.
    ^ instance
!

createSoftLinkIn:aFile
    "create an new soft link in a files directory"

    |instance|

    instance := self new.
    instance createSoftLinkIn:aFile.
    ^ instance
! !

!FileOperation::Create class methodsFor:'documentation'!

version
    ^ '$Header: /cvs/stx/stx/libtool/FileOperation.st,v 1.55 2004-08-03 10:04:44 cg Exp $'
! !

!FileOperation::Create methodsFor:'accessing'!

createdFile
    "return the value of the instance variable 'createdFile' (automatically generated)"

    ^ createdFile
!

createdFile:something
    "set the value of the instance variable 'createdFile' (automatically generated)"

    createdFile := something.
! !

!FileOperation::Create methodsFor:'actions'!

createDirectoryIn:startDirectory
    |defaultDirectory|

    "/ stupid - that one already exists
"/    LastCreatedDirectory notNil ifTrue:[
"/        defaultDirectory := LastCreatedDirectory baseName.
"/    ].
    
    ^ self createDirectoryIn:startDirectory initialAnswer:defaultDirectory
!

createDirectoryIn:startDirectory initialAnswer:initialAnswerArg
    |resources initialAnswer msg startBaseName newName newDir|

    resources := AbstractFileBrowser classResources.

    startBaseName := startDirectory baseName.
    initialAnswer := initialAnswerArg.
    (startDirectory construct:initialAnswer) exists ifTrue:[
        initialAnswer := nil.
    ].
    newName := Dialog
                    request:(resources string:'Create New Directory in %1:' with:startBaseName allBold)
                    initialAnswer:initialAnswer
                    okLabel:(resources string:'Create')
                    title:(resources string:'Create Directory')
                    onCancel:[
                        self result:false. 
                        ^ self
                    ].
    newName isEmpty ifTrue:[
        self result:false. 
        ^ self
    ].
    newDir := startDirectory construct:newName.
    newDir exists ifTrue:[
        Dialog warn:(newName, ' already exists.').
        result := false.
        ^ self
    ].

    newDir makeDirectory ifFalse:[
        msg := errorString := ('cannot create directory '', newName,'' !!') , '(', (OperatingSystem lastErrorString) , ')'.
        errorString := msg.
        Dialog warn:errorString.
        result := false.
        ^ self
    ].
    self createdFile:newDir.
    LastCreatedDirectory := newDir.
    result := true.
!

createFileIn:aFile
    "create an empty file"

    |resources aStream msg file directory newName defaultFile|

    resources := AbstractFileBrowser classResources.

    aFile isDirectory ifTrue:[
        directory := aFile
    ] ifFalse:[
        directory := aFile directory.
        file := aFile
    ].
    LastCreatedFile isNil ifTrue:[
        defaultFile := aFile baseName.
    ] ifFalse:[
        defaultFile := LastCreatedFile baseName.
    ].
    newName := Dialog
                    request:(resources string:'Create New File in %1:' with:directory baseName allBold)
                    initialAnswer:defaultFile
                    okLabel:(resources string:'Create')
                    title:(resources string:'Create File')
                    onCancel:[
                        self result:false. 
                        ^ self
                    ].
    newName isEmpty ifTrue:[
        self result:false. 
    ] ifFalse:[
        | newFile |
        newFile := directory construct:newName.
        newFile exists ifTrue:[
            (Dialog 
                confirm:(newName, ' already exists truncate ?')
                yesLabel:('Truncate')
                noLabel:('Cancel'))
            ifFalse:[
                self result:false. 
                ^ self
            ].
        ].
        FileStream openErrorSignal handle:[:ex|
            msg := ('Cannot create file '', newName,'' !!') , '(' , (FileStream lastErrorString) , ')'.
            errorString := msg.
            self result:false. 
            ^ Dialog warn:errorString
        ] do:[    
            aStream := newFile newReadWriteStream.
        ].
        aStream close.
        self createdFile:newFile.
        LastCreatedFile := newFile.
        self result:true. 
    ].
!

createHardLinkIn:aFile
    "create an new hard link in a files directory"

    self createLinkIn:aFile soft:false.
!

createLinkIn:aFile soft:symbolic
    "ask for the link target;
     then, create an new soft or hard link in aFile's directory"

    |resources newPath oldPath box string if1 if2|

    resources := AbstractFileBrowser classResources.

    aFile isDirectory ifTrue:[
        newPath := aFile asValue.
        oldPath := aFile asValue.
    ] ifFalse:[
        newPath := aFile directory asValue.
        oldPath := aFile asValue.
    ].

    box := Dialog new.
    box label:'Create Link'.

    string := 'Create ', (symbolic ifTrue:['Symbolic'] ifFalse:['Hard']) ,' Link from:'.
    (box addTextLabel:(resources string:string)) adjust:#left.
    if1 := box addFilenameInputFieldOn:newPath in:nil tabable:true.
    (box addTextLabel:(resources string:'to:')) adjust:#left.
    if2 := box addFilenameInputFieldOn:oldPath in:nil value tabable:true.

    box addAbortAndOkButtons.

    aFile isDirectory not ifTrue:[
        box focusOnField:if1.
    ].
    box showAtPointer.

    box accepted ifFalse:[
        self result:false.
    ] ifTrue:[
        self doCreateLinkFrom:(oldPath value) to:(newPath value) soft:symbolic.
    ].
!

createSoftLinkIn:aFile
    "create an new soft link in a files directory"

    self createLinkIn:aFile soft:true.
!

doCreateLinkFrom:oldPath to:newPath soft:symbolic
    "actually create a soft or hard link"

    |resources err newPathFile oldPathFile|

    resources := AbstractFileBrowser classResources.

    (oldPath size == 0) ifTrue:[
        self operationError:'no source entered'.
        ^ self.
    ].
    (newPath size == 0) ifTrue:[
        self operationError:'no link name entered'.
        ^ self.
    ].

    newPathFile := newPath asFilename.
    newPathFile exists ifTrue:[
        self operationError:(resources string:'%1 already exists' with:newPath allBold).
        ^ self.
    ].
    oldPathFile := oldPath asFilename.
    oldPathFile exists not ifTrue:[
        symbolic ifTrue:[
            oldPathFile isAbsolute ifTrue:[
                self operationError:(resources string:'%1 does not exist' with:oldPath allBold).
                ^ self.
            ].
            (newPathFile directory construct:oldPath) exists ifFalse:[
                Dialog warn:(resources string:'%1 does not exist (Warning only)' with:oldPath allBold).
            ].
        ] ifFalse:[
            self operationError:(resources string:'%1 does not exist' with:oldPath allBold).
            ^ self.
        ].
    ].
    ((symbolic not) and:[oldPathFile isDirectory]) ifTrue:[
        self operationError:(resources string:'%1 is a directory' with:oldPath allBold).
        ^ self.
    ].
    ErrorSignal handle:[:ex |
        err := ex errorString.
        self operationError:err.
    ] do:[
        symbolic ifTrue:[
            OperatingSystem createSymbolicLinkFrom:oldPath to:newPath.
        ] ifFalse:[
            OperatingSystem createHardLinkFrom:oldPath to:newPath
        ].
        self createdFile:newPathFile.
        self result:true.
    ].
!

operationError:msg
    self result:false.
    Dialog warn:msg.
    self errorString:msg.
! !

!FileOperation::Delete class methodsFor:'actions'!

deleteFile:aFileOrDirectory
    "delete current selected files/directories
    "

    |instance|

    instance := self new.
    instance deleteFile:aFileOrDirectory.
    ^ instance
!

deleteFiles:aColOfFiles
    "delete current selected files/directories
    "
    ^ self deleteFiles:aColOfFiles confirm:true
!

deleteFiles:aColOfFiles confirm:confirm
    "delete current selected files/directories
    "

    |instance|

    instance := self new.
    instance deleteFiles:aColOfFiles confirm:confirm.
    ^ instance
! !

!FileOperation::Delete class methodsFor:'documentation'!

version
    ^ '$Header: /cvs/stx/stx/libtool/FileOperation.st,v 1.55 2004-08-03 10:04:44 cg Exp $'
! !

!FileOperation::Delete methodsFor:'actions'!

deleteFile:aFileOrDirectory

    | file isDirectory |

    aFileOrDirectory notNil ifTrue:[
        file := aFileOrDirectory asFilename.

        isDirectory := file isDirectory.

        Error handle:[:ex|
            "was not able to remove it"
            Dialog warn:(ex description, '\' withCRs, ex signal notifierString).
"/                Smalltalk beep.
            self errorString:(ex description, ' - ', ex signal notifierString).
            result := false.
            ^ self.
        ] do:[
            isDirectory ifTrue:[file recursiveRemove] ifFalse:[file remove].

        ].
        "/ flush parent directory or directory
    ].
    DirectoryContents flushCachedDirectoryFor:(file directory).
    result := true.

    "Modified: / 17-03-2004 / 12:42:02 / cg"
!

deleteFiles:colOfFiles
    "delete current selected files/directories
    "
    ^ self deleteFiles:colOfFiles confirm:true.
!

deleteFiles:colOfFiles confirm:confirm
    "delete current selected files/directories
    "
    |resources answer nFilesToDelete ask labels values fileTypeString msg lbls vals|

    ask := confirm.
    resources := AbstractFileBrowser classResources.

    nFilesToDelete := colOfFiles size.
    colOfFiles do:[:filenameOrString |
        |filename askForNonEmptyDirectory skip|

        filename := filenameOrString asFilename.

        skip := false.
        fileTypeString := ''.
        filename isSymbolicLink ifTrue:[
            fileTypeString := 'symbolic link '.
        ] ifFalse:[        
            filename exists ifFalse:[ 
                (Dialog 
                    confirm:('%1 does not exist.' bindWith:filename asString allBold)
                    yesLabel:(resources string:'Proceed')
                    noLabel:(resources string:'Cancel')) 
                ifFalse:[
                    ^ self.
                ].
                skip := true.
            ]
        ].
        skip ifFalse:[
            ask ifTrue:[
                nFilesToDelete = 1 ifTrue:[
                    labels := #('No' 'Yes').
                    values := #(#no #yes).
                ] ifFalse:[
                    labels := #('Cancel' 'No' 'Yes' 'Yes to All' ).
                    values := #(#cancel #no #yes #yesToAll).
                ].
                msg := nFilesToDelete = 1 
                            ifTrue:'Really delete\\%1%2 ?' 
                            ifFalse:'Really delete\\%1%2 \\(%3 files alltogether)'.
                answer := Dialog 
                    confirmWithCancel:(resources 
                                        stringWithCRs:msg 
                                        with:fileTypeString
                                        with:(filename asString allBold)
                                        with:nFilesToDelete)
                    labels:(resources array:labels)
                    values:values
                    default:(values indexOf:#yes).
            ] ifFalse:[
                answer := #yesToAll.
            ].

            answer == #cancel ifTrue:[
                ^ self.
            ].

            answer == #yesToAll ifTrue:[
                ask := false.
                answer := #yes.
            ].

            answer == #yes ifTrue:[
                askForNonEmptyDirectory := true.
                filename isSymbolicLink ifFalse:[
                    filename isNonEmptyDirectory ifTrue:[
                        colOfFiles size == 1 ifTrue:[
                            lbls := #('Cancel' 'Remove').
                            vals := #(false true).
                        ] ifFalse:[
                            lbls := #('Cancel All' 'Keep' 'Remove').
                            vals := #(nil false true).
                        ].
                        askForNonEmptyDirectory := Dialog
                                    confirmWithCancel:(resources 
                                                        stringWithCRs:'Directory ''%1'' is not empty\remove anyway ?' 
                                                        with:filename pathName allBold) 
                                    labels:( resources array:lbls )
                                    values:vals 
                                    default:vals size.
                        askForNonEmptyDirectory == nil ifTrue:[
                            ^ self
                        ].
                    ].
                ].
                askForNonEmptyDirectory ifTrue:[
                    self deleteFile:filename.
                ]
            ].
        ].
    ].
! !

!FileOperation::Move class methodsFor:'actions'!

moveFile:aSourceFile to:aDestFile
    "delete current selected files/directories
    "

    |instance|

    instance := self new.
    instance moveFile:aSourceFile to:aDestFile.
    ^ instance
!

moveFile:aSourceFile to:aDestFile withOverWriteWarning:overWriteWarning
    "delete current selected files/directories
    "

    |instance|

    instance := self new.
    instance moveFile:aSourceFile to:aDestFile withOverWriteWarning:overWriteWarning.
    ^ instance
!

moveFile:aSourceFile to:aDestFile withOverWriteWarning:overWriteWarning moveFileIfSame:move
    "delete current selected files/directories
    "

    |instance|

    instance := self new.
    instance moveFile:aSourceFile to:aDestFile withOverWriteWarning:overWriteWarning moveFileIfSame:move.
    ^ instance
!

moveFiles:aColOfSourceFiles to:aDirectory
    "delete current selected files/directories
    "

    |instance|

    instance := self new.
    instance moveFiles:aColOfSourceFiles to:aDirectory.
    ^ instance
!

moveFiles:aColOfSourceFiles to:aDirectory withOverWriteWarning:overWriteWarning
    "delete current selected files/directories
    "

    |instance|

    instance := self new.
    instance moveFiles:aColOfSourceFiles to:aDirectory withOverWriteWarning:overWriteWarning.
    ^ instance
!

moveFiles:aColOfSourceFiles to:aDirectory withOverWriteWarning:overWriteWarning moveFileIfSame:move
    "delete current selected files/directories
    "

    |instance|

    instance := self new.
    instance moveFiles:aColOfSourceFiles to:aDirectory withOverWriteWarning:overWriteWarning moveFileIfSame:move.
    ^ instance
! !

!FileOperation::Move class methodsFor:'documentation'!

version
    ^ '$Header: /cvs/stx/stx/libtool/FileOperation.st,v 1.55 2004-08-03 10:04:44 cg Exp $'
! !

!FileOperation::Move methodsFor:'accessing'!

colOfMovedFiles
    "return the value of the instance variable 'colOfMovedFiles' (automatically generated)"

    colOfMovedFiles isNil ifTrue:[
        colOfMovedFiles := OrderedCollection new.
    ].
    ^ colOfMovedFiles
! !

!FileOperation::Move methodsFor:'actions'!

moveFile:aSourceFile to:aDestFile

    ^ self moveFile:aSourceFile to:aDestFile withOverWriteWarning:true.
!

moveFile:aSourceFile to:aDestFile withOverWriteWarning:overWriteWarning

    ^ self moveFile:aSourceFile to:aDestFile withOverWriteWarning:overWriteWarning moveFileIfSame:true
!

moveFile:aSourceFile to:aDestFile withOverWriteWarning:overWriteWarning moveFileIfSame:move

    |newFile fileString targetDirectory targetIsDirectory suffix doMove|

    targetIsDirectory := aDestFile isDirectory.
    targetIsDirectory ifTrue:[
        targetDirectory := aDestFile.
        newFile := aDestFile construct:(aSourceFile baseName).
    ] ifFalse:[
        targetDirectory := aDestFile directory.
        newFile := aDestFile.
    ].
    "/ do not copy if destination directory doest exist.
    (targetDirectory exists not) ifTrue:[
        Dialog warn:'Cannot move to non-existing directory ', targetDirectory asString. 
        result := false.
        ^ self
    ].
    (newFile exists) ifTrue:[
        ((newFile asString = aSourceFile asString) and:[move]) ifTrue:[
            [newFile exists] whileTrue:[
                suffix := newFile suffix.
                fileString := newFile baseName withoutSuffix, self class copyMoveIfExistSuffixString, '.', suffix.
                newFile := targetDirectory construct:fileString.
            ].
        ] ifFalse:[
            overWriteWarning ifTrue:[
                doMove := self fileExistDialogForNewFile:newFile oldFile:aSourceFile withCancel:false withRemoveIfSame:true.
                doMove == #removeSource ifTrue:[ 
                    self halt.
                    result := false.
                    ^ self.
                ].
                doMove == #removeDestination ifTrue:[ 
                    self halt.
                    result := false.
                    ^ self.
                ].
                doMove == true ifFalse:[ 
                    result := false.
                    ^ self.
                ].

            ] ifFalse:[
                result := false.
                ^ self.
            ]
        ].
    ].
    Error handle:[:ex|
        "was not able to copy it"
        WarningBox warn:'Error in copy file Operation: ', ex errorString.
        self errorString:('Error in copy file Operation- ', ex description asString).
        result := false.
        ^ self
    ] do:[
        aSourceFile moveTo:newFile.
    ].
    DirectoryContents flushCachedDirectoryFor:(aSourceFile directory).
    result := true.
!

moveFiles:aColOfSourceFiles to:aDirectory

    ^ self moveFiles:aColOfSourceFiles to:aDirectory withOverWriteWarning:true
!

moveFiles:aColOfSourceFiles to:aDirectory withOverWriteWarning:overWriteWarning

    ^ self moveFiles:aColOfSourceFiles to:aDirectory withOverWriteWarning:overWriteWarning moveFileIfSame:true
!

moveFiles:aColOfSourceFiles to:aDirectory withOverWriteWarning:overWriteWarning moveFileIfSame:move

    |newFile suffix fileString doMove doRemoveSource doRemoveDestination|

    aDirectory exists ifFalse:[
        (Dialog confirm:(FileBrowser classResources 
                            stringWithCRs:'Non-existing directory "%1" .\Create ?' 
                            with:aDirectory asString allBold)) ifFalse:[
            result := false.
            ^ self
        ].
        aDirectory makeDirectory.
        aDirectory exists ifFalse:[
            Dialog warn:(FileBrowser classResources 
                                stringWithCRs:'Cannot create directory "%1" !!\Create ?.' 
                                with:aDirectory asString allBold).
            result := false.
            ^ self
        ]
    ].
    (aDirectory isDirectory) ifFalse:[
        Dialog warn:('Destination %1 is not a directory.' bindWith:aDirectory asString allBold).
        result := false.
        ^ self
    ].
    aColOfSourceFiles do:[: filename |
        newFile := aDirectory construct:filename baseName.

        doMove := true.
        doRemoveSource := false.
        doRemoveDestination := false.

        (newFile exists) ifTrue:[
            ((newFile asString = filename asString) and:[move]) ifTrue:[
                [newFile exists] whileTrue:[
                    suffix := newFile suffix.
                    fileString := newFile baseName withoutSuffix, self class copyMoveIfExistSuffixString, '.', suffix.
                    newFile := aDirectory construct:fileString.
                ].
            ] ifFalse:[
                overWriteWarning ifTrue:[
                    doMove := self fileExistDialogForNewFile:newFile oldFile:filename withCancel:(aColOfSourceFiles size > 1) withRemoveIfSame:true.
                    doMove isNil ifTrue:[   "/ cancel
                        result := false.
                        ^ self.
                    ].
                    (doMove == #removeSource) ifTrue:[
                        doRemoveSource := true.
                        doMove := false
                    ] ifFalse:[ 
                        (doMove == #removeDestination) ifTrue:[
                            doRemoveDestination := true.
                            doMove := false
                        ]
                    ]
                ]
            ].
        ].

        (doMove or:[doRemoveSource or:[doRemoveDestination]]) ifTrue:[
            Error handle:[:ex|
                "was not able to copy it"
                |descriptionString|

                result := false.
                descriptionString := ex description asString.
                self errorString:(' Error in Move-File Operation:', descriptionString).
                ( Dialog 
                    confirm:(' Error in Move-File Operation: ', descriptionString) 
                    title:'Move'
                    yesLabel:'Continue' 
                    noLabel:'Abort'
                ) ifFalse:[
                    ^ self.
                ].
            ] do:[
                doRemoveSource ifTrue:[
                    filename remove
                ] ifFalse:[
                    doRemoveDestination ifTrue:[
                        newFile remove
                    ] ifFalse:[
                        filename moveTo:newFile.
                    ]
                ]
            ].
            self colOfMovedFiles add:filename
        ]
    ].
    DirectoryContents flushCachedDirectoryFor:aDirectory.
    result := true.
! !

!FileOperation::Rename class methodsFor:'actions'!

renameFile:oldFile to:newName
    "move from to
    "

    |instance|

    instance := self new.
    instance renameFile:oldFile to:newName.
    ^ instance
!

renameFiles:aColOfFiles 
    "move from to
    "

    |instance|

    instance := self new.
    instance renameFiles:aColOfFiles.
    ^ instance
! !

!FileOperation::Rename class methodsFor:'documentation'!

version
    ^ '$Header: /cvs/stx/stx/libtool/FileOperation.st,v 1.55 2004-08-03 10:04:44 cg Exp $'
! !

!FileOperation::Rename methodsFor:'accessing'!

renamedFiles
    "return the value of the instance variable 'lastRenamedFile' (automatically generated)"

    renamedFiles isNil ifTrue:[
        renamedFiles := OrderedCollection new.
    ].
    ^ renamedFiles
! !

!FileOperation::Rename methodsFor:'actions'!

renameFile:oldFile to:newName
    "rename a file (or directory)"

    |newFile msg resources|

    (oldFile isNil or:[newName isNil]) ifTrue:[
        result := false.
        ^ self.
    ].
    (oldFile asString isBlank or:[newName isBlank]) ifTrue:[
        result := false.
        ^ self.
    ].
    newName asFilename isAbsolute ifTrue:[
        newFile := newName asFilename.
    ] ifFalse:[
        (oldFile baseName = newName) ifTrue:[
            result := false
        ].
        newFile := oldFile directory construct:newName.
    ].

    oldFile pathName = newFile pathName ifTrue:[
        ^ self.
    ].

    resources := Dialog classResources.

    OperatingSystem errorSignal handle:[:ex|
        msg := resources 
                stringWithCRs:'Cannot rename file %1 to %2 !!\\(%3)' 
                with:oldFile baseName 
                with:newName 
                with:(OperatingSystem lastErrorString).
        Dialog warn:msg withCRs.
        result := false.
        ^ self.
    ] do:[
        newFile exists ifTrue:[
            (newFile sameContentsAs:oldFile) ifTrue:[
                msg := '%1 exists [with same contents] - rename (i.e. overwrite) anyway ?'
            ] ifFalse:[
                msg := '%1 exists - rename (i.e. overwrite) anyway ?'
            ].
            (Dialog confirmWithCancel:(resources string:msg with:newName allBold) default:false) ifFalse:[
                result := false.
                ^ self.
            ]
        ].
        oldFile renameTo:newFile.
        self renamedFiles add:newFile.
    ].
    result := true.
!

renameFiles:aColOfFiles 
    "rename the selected file(s)"

    |resources queryBox b lastNewName lastOldName initialText oldName newName renameAll doRename|

    resources := AbstractFileBrowser classResources.
    renameAll := false.

    queryBox := FilenameEnterBox new.
    queryBox okText:(resources string:'Rename').

    aColOfFiles size > 1 ifTrue:[
        b := queryBox addAbortButtonLabelled:(resources string:'Cancel All').
        b action:[^ self].
        queryBox addButton:(Button label:(resources string:'Rename All') action:[renameAll := true. queryBox okPressed]) before:(queryBox okButton).
    ].
    aColOfFiles do:[:oldFile |
        oldName := oldFile baseName asString.
        lastNewName notNil ifTrue:[
            initialText := FileBrowser goodRenameDefaultForFile:oldName lastOld:lastOldName lastNew:lastNewName
        ].
        doRename := false.
        renameAll ifTrue:[
            doRename := true.
            newName := initialText.
        ] ifFalse:[
            queryBox title:(resources string:'Rename %1 to:' with:(oldName allBold)).
            queryBox initialText:(initialText ? oldName).
            queryBox action:[:newEnteredName | newName := newEnteredName. doRename := true.].
            queryBox show "showAtPointer".
        ].
        doRename ifTrue:[
            (self renameFile:oldFile to:newName asString) ifTrue:[
                result := true
            ].
            lastOldName := oldName.
            lastNewName := newName.
        ].
    ]
! !

!FileOperation class methodsFor:'documentation'!

version
    ^ '$Header: /cvs/stx/stx/libtool/FileOperation.st,v 1.55 2004-08-03 10:04:44 cg Exp $'
! !