########################################################################
# $Header: /var/local/cvsroot/4Suite/Ft/Server/Client/Commands/Delete.py,v 1.13 2004/09/23 21:17:04 mbrown Exp $
"""
Implementation of '4ss delete' command
(functions defined here are used by the Ft.Lib.CommandLine framework)

Copyright 2004 Fourthought, Inc. (USA).
Detailed license and copyright information: http://4suite.org/COPYRIGHT
Project home, documentation, distributions: http://4suite.org/
"""

__doc__ = """This command will delete from a 4Suite repository all \
resources with paths matching a given pattern. The pattern may contain \
shell-style wildcards as supported by Python's fnmatch module (but you \
probably have to escape them from being matched by your own shell \
first). If necessary, you will be prompted first for credentials and \
access info to connect to the repository. Aliases are normally \
traversed, so in order to delete an Alias, use the --no-traverse \
option."""

import sys, fnmatch, posixpath

from Ft.Rdf import Model
from Ft.Server.Client import FtServerClientException
from Ft.Server.Client.Commands import CommandUtil
from Ft.Server.Common import Schema


def Run(options, args):
    system_path_prefix = '/ftss/'
    promptfirst = options.get('interactive')
    prompt = "Delete '%s'? "
    affirmative_answer = ('y', 'yes')
    all_answer = ('a', 'all')
    repo = CommandUtil.GetRepository(options, '4ss.delete')
    if repo is not None:
        commit = False
        try:
            path = posixpath.normpath(args['path'])
            ta = ""
            if options.has_key('no-traverse'):
                ta = ';no-traverse'
            model = repo.getModel()
            gave_warning = False
            force = False
            statements = model.complete(None, Schema.TYPE, None)
            deleted = {}
            for stmt in statements:
                subject = stmt.subject
                if fnmatch.fnmatchcase(subject, path):
                    # we may have deleted an ancestor container already
                    already_deleted = False
                    for p in deleted.keys():
                        if subject.startswith(p + '/'):
                            already_deleted = True
                            break
                    if already_deleted:
                        continue

                    # deleting /ftss can kill ya
                    is_system = path.startswith(system_path_prefix)
                    if is_system:
                        if not gave_warning:
                            sys.stderr.write("WARNING: Deleting system resources may cause instability.\n")
                            gave_warning = True
                        if not force:
                            sys.stderr.write('%s(yes/no/all): ' % (prompt % subject))
                            sys.stderr.flush()
                            line = sys.stdin.readline()
                            if line and line[-1] == '\n':
                                line = line[:-1]
                            line = line.lower()
                            if line in all_answer:
                                force = True
                            elif line not in affirmative_answer:
                                continue

                    elif promptfirst:
                        sys.stderr.write('%s\n' % (prompt % subject))
                        sys.stderr.flush()
                        line = sys.stdin.readline()
                        if line and line[-1] == '\n':
                            line = line[:-1]
                        if line.lower() not in affirmative:
                            continue

                    sys.stderr.write("Deleting: %s\n" % subject)
                    sys.stderr.flush()
                    repo.deleteResource(subject + ta)
                    deleted[subject] = True

            commit = True

        finally:
            try:
                if commit:
                    repo.txCommit()
                else:
                    sys.stderr.write("Resource(s) not deleted.\n")
                    sys.stderr.flush()
                    repo.txRollback()
            except:
                pass

    return


def Register():
    from Ft.Lib.CommandLine import Options, Command, Arguments
    cmd = Command.Command('delete',
                          'Delete a resource from a repository',
                          '/fourthought.com',
                          __doc__,
                          function = Run,
                          arguments = [Arguments.RequiredArgument('path',
                                                                  "the path of the resource to delete; can be a regular expression",
                                                                  str),
                                       ],
                          options = Options.Options([Options.Option(None,
                                                                    'no-traverse',
                                                                    "don't traverse aliases"),
                                                     Options.Option('i',
                                                                    'interactive',
                                                                    "prompt for confirmation before deleting"),
                                                     ]),

                          fileName = __file__,
                          )
    return cmd
