summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xTools/scripts/ftpmirror.py75
1 files changed, 50 insertions, 25 deletions
diff --git a/Tools/scripts/ftpmirror.py b/Tools/scripts/ftpmirror.py
index f25864b..123f479 100755
--- a/Tools/scripts/ftpmirror.py
+++ b/Tools/scripts/ftpmirror.py
@@ -1,22 +1,7 @@
#! /usr/bin/env python
-# Mirror a remote ftp subtree into a local directory tree.
-# Basic usage: ftpmirror [options] host remotedir localdir
-#
-# XXX To do:
-# - handle symbolic links
-# - back up .mirrorinfo before overwriting
-# - use pickles for .mirrorinfo?
-
-import os
-import sys
-import time
-import getopt
-import string
-import ftplib
-from fnmatch import fnmatch
+"""Mirror a remote ftp subtree into a local directory tree.
-usage_msg = """
usage: ftpmirror [-v] [-q] [-i] [-m] [-n] [-r] [-s pat]
[-l username [-p passwd [-a account]]]
hostname [remotedir [localdir]]
@@ -25,17 +10,31 @@ usage: ftpmirror [-v] [-q] [-i] [-m] [-n] [-r] [-s pat]
-i: interactive mode
-m: macintosh server (NCSA telnet 2.4) (implies -n -s '*.o')
-n: don't log in
--r: remove files no longer pertinent
+-r: remove local files/directories no longer pertinent
-l username [-p passwd [-a account]]: login info (default anonymous ftp)
-s pat: skip files matching pattern
hostname: remote host
remotedir: remote directory (default initial)
localdir: local directory (default current)
"""
+
+# XXX To do:
+# - handle symbolic links
+# - back up .mirrorinfo before overwriting
+
+import os
+import sys
+import time
+import getopt
+import string
+import ftplib
+from fnmatch import fnmatch
+
+# Print usage message and exit
def usage(*args):
sys.stdout = sys.stderr
for msg in args: print msg
- print usage_msg
+ print __doc__
sys.exit(2)
verbose = 1 # 0 for -q, 2 for -v
@@ -45,6 +44,7 @@ rmok = 0
nologin = 0
skippats = ['.', '..', '.mirrorinfo']
+# Main program: parse command line and start processing
def main():
global verbose, interactive, mac, rmok, nologin
try:
@@ -94,6 +94,7 @@ def main():
#
mirrorsubdir(f, localdir)
+# Core logic: mirror one subdirectory (recursively)
def mirrorsubdir(f, localdir):
pwd = f.pwd()
if localdir and not os.path.isdir(localdir):
@@ -137,7 +138,7 @@ def mirrorsubdir(f, localdir):
continue
if words[-2] == '->':
if verbose > 1:
- print 'Skipping symbolic link %s -> %s' % \
+ print 'Skipping symbolic link %s -> %s' % \
(words[-3], words[-1])
continue
filename = words[-1]
@@ -259,12 +260,8 @@ def mirrorsubdir(f, localdir):
print 'Local file', fullname,
print 'is no longer pertinent'
continue
- if verbose: print 'Removing local file', fullname
- try:
- os.unlink(fullname)
- except os.error, msg:
- print "Can't remove local file %s: %s" % \
- (fullname, str(msg))
+ if verbose: print 'Removing local file/dir', fullname
+ remove(fullname)
#
# Recursively mirror subdirectories
for subdir in subdirs:
@@ -294,6 +291,34 @@ def mirrorsubdir(f, localdir):
else:
if verbose > 1: print 'OK.'
+# Helper to remove a file or directory tree
+def remove(fullname):
+ if os.path.isdir(fullname) and not os.path.islink(fullname):
+ try:
+ names = os.listdir(fullname)
+ except os.error:
+ names = []
+ ok = 1
+ for name in names:
+ if not remove(os.path.join(fullname, name)):
+ ok = 0
+ if not ok:
+ return 0
+ try:
+ os.rmdir(fullname)
+ except os.error, msg:
+ print "Can't remove local directory %s: %s" % \
+ (fullname, str(msg))
+ return 0
+ else:
+ try:
+ os.unlink(fullname)
+ except os.error, msg:
+ print "Can't remove local file %s: %s" % \
+ (fullname, str(msg))
+ return 0
+ return 1
+
# Wrapper around a file for writing to write a hash sign every block.
class LoggingFile:
def __init__(self, fp, blocksize, outfp):