Replace boost::scoped_ptr with std::unique_ptr.
[cumulus.git] / cumulus-sync
index 9fb835c..9f31a29 100755 (executable)
@@ -1,7 +1,27 @@
 #!/usr/bin/python
 #
+# Cumulus: Efficient Filesystem Backup to the Cloud
+# Copyright (C) 2008 The Cumulus Developers
+# See the AUTHORS file for a list of contributors.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
 # Tool for copying cumulus archives from one source to another.
 
+from __future__ import division, print_function, unicode_literals
+
 import os, sys
 
 # Automatically set Python path, based on script directory.  This should be
@@ -12,27 +32,37 @@ sys.path.append(os.path.join(script_directory, 'python'))
 import cumulus
 import cumulus.store
 
-store1 = cumulus.store.open(sys.argv[1])
-store2 = cumulus.store.open(sys.argv[2])
+store1 = cumulus.BackendWrapper(sys.argv[1])
+store2 = cumulus.BackendWrapper(sys.argv[2])
 
-source = cumulus.ObjectStore(cumulus.LowlevelDataStore(store1))
+source = cumulus.CumulusStore(store1)
 
-filter = set()
-for s in sys.argv[3:]:
-    filter.add(s)
+items_required = set()
+snapshots = sys.argv[3:]
+if not snapshots:
+    snapshots = list(source.list_snapshots())
+for s in snapshots:
+    items_required.add(s)
     d = cumulus.parse_full(source.load_snapshot(s))
-    filter.update(d['Segments'].split())
-
-for ty in ('segments', 'checksums', 'snapshots'):
-    for f in sorted(store1.list(ty)):
-        m = cumulus.store.type_patterns[ty].match(f)
-        if not m: continue
-        if filter and m.group(1) not in filter:
-            continue
-
-        print ty, f
-        try:
-            store2.stat(ty, f)
-        except cumulus.store.NotFoundError:
-            store2.put(ty, f, store1.get(ty, f))
-            print "    [sent]"
+    items_required.update(d['Segments'].split())
+print("Required:", len(items_required))
+
+files_present = set()
+for filetype in cumulus.SEARCH_PATHS:
+    for (name, path) in store2.list_generic(filetype):
+        items_required.discard(name)
+        files_present.add(path)
+print("Files already present:", len(sorted(files_present)))
+
+files_required = []
+items_found = set()
+for filetype in cumulus.SEARCH_PATHS:
+    for (name, path) in store1.list_generic(filetype):
+        if name in items_required:
+            files_required.append(path)
+            items_found.add(name)
+files_required.sort()
+
+for i, f in enumerate(files_required):
+    print("[%d/%d] %s" % (i + 1, len(files_required), f))
+    store2.raw_backend.put(f, store1.raw_backend.get(f))