10
10
import re
11
11
import time
12
12
import sys
13
- import stat
14
13
15
14
WILDCARDS_RE = re .compile ('([*?[])' )
16
15
KILO = 1024
19
18
_have_AFS = None
20
19
whoami = os .path .basename (sys .argv [0 ])
21
20
21
+
22
22
class DeleteError (Exception ):
23
23
pass
24
24
25
+
25
26
def perror (message , ** kwargs ):
26
27
"""
27
28
Format an error message, log it in the debug log
@@ -33,12 +34,14 @@ def perror(message, **kwargs):
33
34
if should_print :
34
35
print >> sys .stderr , msg
35
36
37
+
36
38
def chunks (seq , size ):
37
39
"""
38
40
Break a sequence up into size chunks
39
41
"""
40
42
return (seq [pos :pos + size ] for pos in xrange (0 , len (seq ), size ))
41
43
44
+
42
45
def format_columns (items , singlecol = False , width = 80 ):
43
46
"""
44
47
Pretty-print in optional multi-column format, with padding/spread.
@@ -59,6 +62,7 @@ def format_columns(items, singlecol=False, width=80):
59
62
rv .append ("" .join (item .ljust (col_width + padding ) for item in c ))
60
63
return "\n " .join (rv )
61
64
65
+
62
66
def have_AFS ():
63
67
global _have_AFS , afs
64
68
@@ -71,6 +75,7 @@ def have_AFS():
71
75
_have_AFS = False
72
76
return _have_AFS
73
77
78
+
74
79
def is_mountpoint (path ):
75
80
if os .path .ismount (path ):
76
81
return True
@@ -82,35 +87,41 @@ def is_mountpoint(path):
82
87
logger .debug ("Got exception while checking mount point: %s" , e )
83
88
return False
84
89
90
+
85
91
def has_wildcards (string ):
86
92
return WILDCARDS_RE .search (string ) is not None
87
93
94
+
88
95
def is_deleted (path ):
89
96
"""
90
97
Return True if the file has been 'deleted' by delete(1)
91
98
"""
92
99
return os .path .basename (path ).startswith ('.#' )
93
100
101
+
94
102
def dir_listing (path ):
95
103
"""
96
104
A directory listing with the full path.
97
105
"""
98
106
return [os .path .join (path , x ) for x in os .listdir (path )]
99
107
108
+
100
109
def empty_directory (path ):
101
110
"""
102
111
Return True if the directory is "empty" (that is, any entries
103
112
in it have been deleted)
104
113
"""
105
114
return all (is_deleted (x ) for x in dir_listing (path ))
106
115
116
+
107
117
def relpath (path ):
108
118
"""
109
119
For relative paths that begin with '.', strip off the leading
110
120
stuff.
111
121
"""
112
122
return path [2 :] if path .startswith ('./' ) else path
113
123
124
+
114
125
def undeleted_name (path ):
115
126
"""
116
127
Return the undeleted name of a file. Only the last component
@@ -124,6 +135,7 @@ def undeleted_name(path):
124
135
else :
125
136
return path
126
137
138
+
127
139
def n_days_old (path , n ):
128
140
if n < 0 :
129
141
raise ValueError ("n must not be negative" )
@@ -134,27 +146,34 @@ def n_days_old(path, n):
134
146
logger .debug ("%s modified %d sec ago" , path , mtime )
135
147
return ((time .time () - mtime ) >= (86400 * n ))
136
148
149
+
137
150
def escape_meta (path ):
138
151
return WILDCARDS_RE .sub (r'[\1]' , path )
139
152
153
+
140
154
def to_kb (size ):
141
155
return int (round (float (size ) / KILO ))
142
156
157
+
143
158
def find_deleted_files (file_or_pattern , follow_links = False ,
144
159
follow_mounts = False , recurse_undeleted_subdirs = None ,
145
160
recurse_deleted_subdirs = None , n_days = 0 ):
146
161
147
- logger .debug ("find_deleted_files(%s, links=%s, mounts=%s, recurse_un=%s, recurse_del=%s, ndays=%s)" ,
148
- file_or_pattern , follow_links , follow_mounts , recurse_undeleted_subdirs ,
149
- recurse_deleted_subdirs , n_days )
162
+ logger .debug ("find_deleted_files(%s, links=%s, mounts=%s, recurse_un=%s, "
163
+ "recurse_del=%s, ndays=%s)" ,
164
+ file_or_pattern , follow_links , follow_mounts ,
165
+ recurse_undeleted_subdirs , recurse_deleted_subdirs , n_days )
150
166
rv = []
151
167
# In AFS, without tokens, this is very slow. "Don't do that."
152
168
# The old code called readdir() and lstat'd everything before following.
153
- # The old code also re-implemented glob() with BREs, and we're not doing that.
169
+ # The old code also re-implemented glob() with BREs, and we're not doing
170
+ # that.
154
171
file_list = glob .glob (file_or_pattern ) + glob .glob ('.#' + file_or_pattern )
155
172
if len (file_list ) == 0 :
156
- raise DeleteError ("{0}: {1}" .format (file_or_pattern ,
157
- "No match" if has_wildcards (file_or_pattern ) else os .strerror (errno .ENOENT )))
173
+ raise DeleteError ("{0}: {1}" .format (
174
+ file_or_pattern ,
175
+ "No match" if has_wildcards (file_or_pattern )
176
+ else os .strerror (errno .ENOENT )))
158
177
159
178
for filename in file_list :
160
179
logger .debug ("Examining %s" , filename )
@@ -166,21 +185,26 @@ def find_deleted_files(file_or_pattern, follow_links=False,
166
185
if is_mountpoint (filename ) and not follow_mounts :
167
186
logger .debug ("Skipping mountpoint: %s" , filename )
168
187
continue
169
- if ((is_deleted (filename ) and (recurse_deleted_subdirs != False )) or \
170
- (not is_deleted (filename ) and (recurse_undeleted_subdirs != False ))):
171
- # NOTE: recurse_undeleted_subdirs is being abused as a tristate with 'None'
172
- # meaning "do it on the first time only.
188
+ if ((is_deleted (filename ) and
189
+ (recurse_deleted_subdirs is not False )) or
190
+ (not is_deleted (filename ) and
191
+ (recurse_undeleted_subdirs is not False ))):
192
+ # NOTE: recurse_undeleted_subdirs is being abused as a tristate
193
+ # with 'None' meaning "do it on the first time only.
173
194
logger .debug ("Recursing into %sdeleted directory: %s" ,
174
195
"un" if not is_deleted (filename ) else "" ,
175
196
filename )
176
197
try :
177
198
for item in dir_listing (filename ):
178
199
# Escape metachars before recursing because filenames
179
200
# can in fact contain metacharacters.
180
- rv += find_deleted_files (escape_meta (item ), follow_links , follow_mounts ,
181
- False if recurse_undeleted_subdirs is None else recurse_undeleted_subdirs ,
182
- False if recurse_deleted_subdirs is None else recurse_deleted_subdirs ,
183
- n_days )
201
+ rv += find_deleted_files (
202
+ escape_meta (item ), follow_links , follow_mounts ,
203
+ False if recurse_undeleted_subdirs is None
204
+ else recurse_undeleted_subdirs ,
205
+ False if recurse_deleted_subdirs is None
206
+ else recurse_deleted_subdirs ,
207
+ n_days )
184
208
except OSError as e :
185
209
perror ('{filename}: {error}' , filename = e .filename ,
186
210
error = e .strerror )
0 commit comments