/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/clean_tree.py

  • Committer: Gustav Hartvigsson
  • Date: 2021-01-09 21:36:27 UTC
  • Revision ID: gustav.hartvigsson@gmail.com-20210109213627-h1xwcutzy9m7a99b
Added 'Case Preserving Working Tree Use Cases' from Canonical Wiki

* Addod a page from the Canonical Bazaar wiki
  with information on the scmeatics of case
  perserving filesystems an a case insensitive
  filesystem works.
  
  * Needs re-work, but this will do as it is the
    same inforamoton as what was on the linked
    page in the currint documentation.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005 Canonical Ltd
 
1
# Copyright (C) 2009, 2010 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
 
 
 
17
import errno
18
18
import os
19
19
import shutil
20
20
 
21
 
from bzrlib.osutils import isdir
22
 
from bzrlib.trace import note
23
 
from bzrlib.workingtree import WorkingTree
 
21
from . import (
 
22
    controldir,
 
23
    errors,
 
24
    ui,
 
25
    )
 
26
from .osutils import isdir
 
27
from .trace import note
 
28
from .workingtree import WorkingTree
 
29
from .i18n import gettext
24
30
 
25
31
 
26
32
def is_detritus(subp):
47
53
               dry_run=False, no_prompt=False):
48
54
    """Remove files in the specified classes from the tree"""
49
55
    tree = WorkingTree.open_containing(directory)[0]
50
 
    tree.lock_read()
51
 
    try:
 
56
    with tree.lock_read():
52
57
        deletables = list(iter_deletables(tree, unknown=unknown,
53
 
            ignored=ignored, detritus=detritus))
 
58
                                          ignored=ignored, detritus=detritus))
 
59
        deletables = _filter_out_nested_controldirs(deletables)
54
60
        if len(deletables) == 0:
55
 
            note('Nothing to delete.')
 
61
            note(gettext('Nothing to delete.'))
56
62
            return 0
57
63
        if not no_prompt:
58
64
            for path, subp in deletables:
59
 
                print subp
60
 
            val = raw_input('Are you sure you wish to delete these [y/N]?')
61
 
            if val.lower() not in ('y', 'yes'):
62
 
                print 'Canceled'
 
65
                ui.ui_factory.note(subp)
 
66
            prompt = gettext('Are you sure you wish to delete these')
 
67
            if not ui.ui_factory.get_boolean(prompt):
 
68
                ui.ui_factory.note(gettext('Canceled'))
63
69
                return 0
64
70
        delete_items(deletables, dry_run=dry_run)
65
 
    finally:
66
 
        tree.unlock()
 
71
 
 
72
 
 
73
def _filter_out_nested_controldirs(deletables):
 
74
    result = []
 
75
    for path, subp in deletables:
 
76
        # bzr won't recurse into unknowns/ignored directories by default
 
77
        # so we don't pay a penalty for checking subdirs of path for nested
 
78
        # control dir.
 
79
        # That said we won't detect the branch in the subdir of non-branch
 
80
        # directory and therefore delete it. (worth to FIXME?)
 
81
        if isdir(path):
 
82
            try:
 
83
                controldir.ControlDir.open(path)
 
84
            except errors.NotBranchError:
 
85
                result.append((path, subp))
 
86
            else:
 
87
                # TODO may be we need to notify user about skipped directories?
 
88
                pass
 
89
        else:
 
90
            result.append((path, subp))
 
91
    return result
67
92
 
68
93
 
69
94
def delete_items(deletables, dry_run=False):
70
95
    """Delete files in the deletables iterable"""
 
96
    def onerror(function, path, excinfo):
 
97
        """Show warning for errors seen by rmtree.
 
98
        """
 
99
        # Handle only permission error while removing files.
 
100
        # Other errors are re-raised.
 
101
        if function is not os.remove or excinfo[1].errno != errno.EACCES:
 
102
            raise
 
103
        ui.ui_factory.show_warning(gettext('unable to remove %s') % path)
71
104
    has_deleted = False
72
105
    for path, subp in deletables:
73
106
        if not has_deleted:
74
 
            note("deleting paths:")
 
107
            note(gettext("deleting paths:"))
75
108
            has_deleted = True
76
 
        note('  ' + subp)
77
109
        if not dry_run:
78
110
            if isdir(path):
79
 
                shutil.rmtree(path)
 
111
                shutil.rmtree(path, onerror=onerror)
80
112
            else:
81
 
                os.unlink(path)
 
113
                try:
 
114
                    os.unlink(path)
 
115
                    note('  ' + subp)
 
116
                except OSError as e:
 
117
                    # We handle only permission error here
 
118
                    if e.errno != errno.EACCES:
 
119
                        raise e
 
120
                    ui.ui_factory.show_warning(gettext(
 
121
                        'unable to remove "{0}": {1}.').format(
 
122
                        path, e.strerror))
 
123
        else:
 
124
            note('  ' + subp)
82
125
    if not has_deleted:
83
 
        note("No files deleted.")
 
126
        note(gettext("No files deleted."))