From 0025c8d392f4a4f7c17aafe4aa45fedd9b9c616c Mon Sep 17 00:00:00 2001 From: Zoran Zaric Date: Mon, 6 Dec 2010 13:00:02 +0100 Subject: [PATCH] Adds a strip and strip-path option to bup save. If the strip option is given bup uses all given filenames as base paths and tries to stripe them from long to short. If the strip-path option is given bup strip the given prefix from all paths. Signed-off-by: Zoran Zaric --- cmd/save-cmd.py | 13 ++++++++++++- lib/bup/helpers.py | 33 +++++++++++++++++++++++++++++++++ lib/bup/t/thelpers.py | 18 ++++++++++++++++++ 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/cmd/save-cmd.py b/cmd/save-cmd.py index df51a6c..d8c73cc 100755 --- a/cmd/save-cmd.py +++ b/cmd/save-cmd.py @@ -16,6 +16,8 @@ v,verbose increase log output (can be used more than once) q,quiet don't show progress meter smaller= only back up files smaller than n bytes bwlimit= maximum bytes/sec to transmit to server +strip strips the path to every filename given +strip-path= path-prefix to be stripped when saving """ o = options.Options('bup save', optspec) (opt, flags, extra) = o.parse(sys.argv[1:]) @@ -36,6 +38,9 @@ if opt.date: else: date = time.time() +if opt.strip and opt.strip_path: + o.fatal("--strip is incompatible with --strip-path") + is_reverse = os.environ.get('BUP_SERVER_REVERSE') if is_reverse and opt.remote: o.fatal("don't use -r in reverse mode; it's automatic") @@ -195,7 +200,13 @@ for (transname,ent) in r.filter(extra, wantrecurse=wantrecurse_during): continue assert(dir.startswith('/')) - dirp = dir.split('/') + if opt.strip: + stripped_base_path = strip_base_path(dir, extra) + dirp = stripped_base_path.split('/') + elif opt.strip_path: + dirp = strip_path(opt.strip_path, dir).split('/') + else: + dirp = dir.split('/') while parts > dirp: _pop(force_tree = None) if dir != '/': diff --git a/lib/bup/helpers.py b/lib/bup/helpers.py index cb78543..3c78c18 100644 --- a/lib/bup/helpers.py +++ b/lib/bup/helpers.py @@ -411,6 +411,39 @@ def parse_date_or_fatal(str, fatal): else: return date +def strip_path(prefix, path): + """Strips a given prefix from a path. + + First both paths are normalized. + + Raises an Exception if no prefix is given. + """ + if prefix == None: + raise Exception('no path given') + + normalized_prefix = realpath(prefix) + print "normalized_prefix: " + normalized_prefix + normalized_path = realpath(path) + print "normalized_path: " + normalized_path + if normalized_path.startswith(normalized_prefix): + return normalized_path[len(normalized_prefix):] + else: + return path + +def strip_base_path(path, base_paths): + """Strips the base path from a given path. + + Determines the base path for the given string and the strips it + using strip_path(). + Iterates over all base_paths from long to short, to prevent that + a too short base_path is removed. + """ + sorted_base_paths = sorted(base_paths, key=len, reverse=True) + for bp in sorted_base_paths: + if path.startswith(realpath(bp)): + return strip_path(bp, path) + return path + # hashlib is only available in python 2.5 or higher, but the 'sha' module # produces a DeprecationWarning in python 2.6 or higher. We want to support diff --git a/lib/bup/t/thelpers.py b/lib/bup/t/thelpers.py index 9f24962..306d39b 100644 --- a/lib/bup/t/thelpers.py +++ b/lib/bup/t/thelpers.py @@ -10,3 +10,21 @@ def test_parse_num(): WVPASSEQ(pn('2 gb'), 2*1024*1024*1024) WVPASSEQ(pn('1e+9 k'), 1000000000 * 1024) WVPASSEQ(pn('-3e-3mb'), int(-0.003 * 1024 * 1024)) + +@wvtest +def test_strip_path(): + prefix = "/var/backup/daily.0/localhost" + empty_prefix = "" + non_matching_prefix = "/home" + path = "/var/backup/daily.0/localhost/etc/" + + WVPASSEQ(strip_path(prefix, path), '/etc') + WVPASSEQ(strip_path(empty_prefix, path), path) + WVPASSEQ(strip_path(non_matching_prefix, path), path) + WVEXCEPT(Exception, strip_path, None, path) + +@wvtest +def test_strip_base_path(): + path = "/var/backup/daily.0/localhost/etc/" + base_paths = ["/var", "/var/backup", "/var/backup/daily.0/localhost"] + WVPASSEQ(strip_base_path(path, base_paths), '/etc') -- 2.39.5