]> arthur.barton.de Git - bup.git/blobdiff - cmd/index-cmd.py
cleanup-mounts-under: Don't fail when /proc/mounts isn't readable
[bup.git] / cmd / index-cmd.py
index 4904c0110747f0f23b7babb90668691b50b17281..6f2adf4e581c1dc288babe4bee3525c2f61ea004 100755 (executable)
@@ -62,7 +62,7 @@ def clear_index(indexfile):
                 raise
 
 
-def update_index(top, excluded_paths):
+def update_index(top, excluded_paths, exclude_rxs):
     # tmax and start must be epoch nanoseconds.
     tmax = (time.time() - 1) * 10**9
     ri = index.Reader(indexfile)
@@ -80,6 +80,7 @@ def update_index(top, excluded_paths):
 
     total = 0
     bup_dir = os.path.abspath(git.repo())
+    index_start = time.time()
     for (path,pst) in drecurse.recursive_dirlist([top], xdev=opt.xdev,
                                                  bup_dir=bup_dir,
                                                  excluded_paths=excluded_paths,
@@ -87,9 +88,13 @@ def update_index(top, excluded_paths):
         if opt.verbose>=2 or (opt.verbose==1 and stat.S_ISDIR(pst.st_mode)):
             sys.stdout.write('%s\n' % path)
             sys.stdout.flush()
-            qprogress('Indexing: %d\r' % total)
+            elapsed = time.time() - index_start
+            paths_per_sec = total / elapsed if elapsed else 0
+            qprogress('Indexing: %d (%d paths/s)\r' % (total, paths_per_sec))
         elif not (total % 128):
-            qprogress('Indexing: %d\r' % total)
+            elapsed = time.time() - index_start
+            paths_per_sec = total / elapsed if elapsed else 0
+            qprogress('Indexing: %d (%d paths/s)\r' % (total, paths_per_sec))
         total += 1
         while rig.cur and rig.cur.name > path:  # deleted paths
             if rig.cur.exists():
@@ -99,11 +104,16 @@ def update_index(top, excluded_paths):
                     hlinks.del_path(rig.cur.name)
             rig.next()
         if rig.cur and rig.cur.name == path:    # paths that already existed
+            try:
+                meta = metadata.from_path(path, statinfo=pst)
+            except (OSError, IOError), e:
+                add_error(e)
+                rig.next()
+                continue
             if not stat.S_ISDIR(rig.cur.mode) and rig.cur.nlink > 1:
                 hlinks.del_path(rig.cur.name)
             if not stat.S_ISDIR(pst.st_mode) and pst.st_nlink > 1:
                 hlinks.add_path(path, pst.st_dev, pst.st_ino)
-            meta = metadata.from_path(path, statinfo=pst)
             # Clear these so they don't bloat the store -- they're
             # already in the index (since they vary a lot and they're
             # fixed length).  If you've noticed "tmax", you might
@@ -129,7 +139,11 @@ def update_index(top, excluded_paths):
             rig.cur.repack()
             rig.next()
         else:  # new paths
-            meta = metadata.from_path(path, statinfo=pst)
+            try:
+                meta = metadata.from_path(path, statinfo=pst)
+            except (OSError, IOError), e:
+                add_error(e)
+                continue
             # See same assignment to 0, above, for rationale.
             meta.atime = meta.mtime = meta.ctime = 0
             meta_ofs = msw.store(meta)
@@ -137,8 +151,10 @@ def update_index(top, excluded_paths):
             if not stat.S_ISDIR(pst.st_mode) and pst.st_nlink > 1:
                 hlinks.add_path(path, pst.st_dev, pst.st_ino)
 
-    progress('Indexing: %d, done.\n' % total)
-    
+    elapsed = time.time() - index_start
+    paths_per_sec = total / elapsed if elapsed else 0
+    progress('Indexing: %d, done (%d paths/s).\n' % (total, paths_per_sec))
+
     hlinks.prepare_save()
 
     if ri.exists():
@@ -169,7 +185,7 @@ def update_index(top, excluded_paths):
 
 
 optspec = """
-bup index <-p|m|s|u> [options...] <filenames...>
+bup index <-p|-m|-s|-u|--clear|--check> [options...] <filenames...>
 --
  Modes:
 p,print    print the index entries for the given names (also works with -u)
@@ -177,7 +193,7 @@ m,modified print only added/deleted/modified files (implies -p)
 s,status   print each filename with a status char (A/M/D) (implies -p)
 u,update   recursively update the index entries for the given file/dir names (default if no mode is specified)
 check      carefully check index file integrity
-clear      clear the index
+clear      clear the default index
  Options:
 H,hash     print the hash for each object next to its name
 l,long     print more information about each file
@@ -185,9 +201,10 @@ no-check-device don't invalidate an entry if the containing device changes
 fake-valid mark all index entries as up-to-date even if they aren't
 fake-invalid mark all index entries as invalid
 f,indexfile=  the name of the index file (normally BUP_DIR/bupindex)
-exclude=   a path to exclude from the backup (can be used more than once)
-exclude-from= a file that contains exclude paths (can be used more than once)
-exclude-rx= skip paths that match the unanchored regular expression
+exclude= a path to exclude from the backup (may be repeated)
+exclude-from= skip --exclude paths in file (may be repeated)
+exclude-rx= skip paths matching the unanchored regex (may be repeated)
+exclude-rx-from= skip --exclude-rx patterns in file (may be repeated)
 v,verbose  increase log output (can be used more than once)
 x,xdev,one-file-system  don't cross filesystem boundaries
 """
@@ -205,6 +222,8 @@ if (opt.fake_valid or opt.fake_invalid) and not opt.update:
     o.fatal('--fake-{in,}valid are meaningless without -u')
 if opt.fake_valid and opt.fake_invalid:
     o.fatal('--fake-valid is incompatible with --fake-invalid')
+if opt.clear and opt.indexfile:
+    o.fatal('cannot clear an external index (via -f)')
 
 # FIXME: remove this once we account for timestamp races, i.e. index;
 # touch new-file; index.  It's possible for this to happen quickly
@@ -234,7 +253,7 @@ if opt.update:
     if not extra:
         o.fatal('update mode (-u) requested but no paths given')
     for (rp,path) in paths:
-        update_index(rp, excluded_paths)
+        update_index(rp, excluded_paths, exclude_rxs)
 
 if opt['print'] or opt.status or opt.modified:
     for (name, ent) in index.Reader(indexfile).filter(extra or ['']):