[PATCH bfiles] bfupdate: detect big files where only the execute bit needs updating
Geoff Crossland
geoff.crossland at linguamatics.com
Tue Jul 5 08:50:07 CDT 2011
# HG changeset patch
# User Geoff Crossland <gcrossland at linguamatics.com>
# Date 1309861085 -3600
# Node ID b18fb7734d6bf5c01d4733065c7455fd96492193
# Parent f0512849f1634922b6edccc162e9553b45f56b37
bfupdate: detect big files where only the execute bit needs updating
diff --git a/bfiles/bfcommands.py b/bfiles/bfcommands.py
--- a/bfiles/bfcommands.py
+++ b/bfiles/bfcommands.py
@@ -396,12 +396,17 @@
store = basestore._open_store(ui, repo)
updated = removed = 0
+ # Build a list of all files that we want to update. Some are
+ # modified but already have the right contents (i.e. only their x
+ # bit has changed), so avoid going to the central store for them.
# Use dirstate.walk() rather than repo.walk() for performance: we do
# not care about unknown files at all, so don't waste time iterating
# over them. Should be safe since users should not create files in
# .hgbfiles; if they do, we'll ignore them here and that's just
# fine.
- want_files = []
+ want_files_count = 0
+ success0 = []
+ still_want = []
for standin in sorted(bfutil.dirstate_walk(repo.dirstate, matcher)):
want_hash = bfutil._read_standin(repo, standin)
filename = bfutil._split_standin(standin)
@@ -409,17 +414,25 @@
if (latest_hash and
latest_hash == want_hash and
os.path.isfile(repo.wjoin(filename))):
- continue
-
- want_files.append((filename, want_hash))
+ want_mode = os.stat(repo.wjoin(standin)).st_mode & 0100
+ latest_mode = os.stat(repo.wjoin(filename)).st_mode & 0100
+ if latest_mode == want_mode:
+ continue
+ else:
+ want_files_count += 1
+ success0.append((filename, want_hash))
+ continue
+ want_files_count += 1
+ still_want.append((filename, want_hash))
# Some revisions might be stashed in .hg/bfiles/{pending,committed}
# -- e.g. anything that has been bfadded, bfrefreshed, or committed,
# but not yet bfput. Go there first: should be faster than hitting
# the central store.
success1 = []
+ t = still_want
still_want = []
- for (filename, hash) in want_files:
+ for (filename, hash) in t:
found = False
for dir in ('pending', 'committed'):
pfilename = repo.join(os.path.join(
@@ -436,12 +449,12 @@
# Now go to the central store for whatever we didn't find locally.
(success2, missing) = store.get(still_want)
- success = success1 + success2
- del success1, success2
- assert len(success) + len(missing) == len(want_files), \
+ success = success0 + success1 + success2
+ del success0, success1, success2
+ assert len(success) + len(missing) == want_files_count, \
('some requested files not accounted for: '
'wanted %d files, got %d, missing %d'
- % (len(want_files), len(success), len(missing)))
+ % (want_files_count, len(success), len(missing)))
# Fix permissions of successfully downloaded files.
umask = os.umask(0777)
diff --git a/tests/test-update.t b/tests/test-update.t
--- a/tests/test-update.t
+++ b/tests/test-update.t
@@ -312,3 +312,31 @@
getting sub/big3
2 big files updated, 0 removed
$ hg bfstatus
+
+create a clone with two changesets that differ only in the x-bit on a big file, then update between them
+ $ old=`umask`
+ $ umask 0070
+ $ cd ..
+ $ hg clone -q repo1 repo3 -r3
+ $ cd repo3
+ $ hg bfupdate -q
+ $ chmod a-x sub/big3
+ $ hg bfrefresh -v
+ sub/big3
+ 1 big files refreshed
+ $ $PYTHON $TESTDIR/lsmode.py sub/big3
+ 100606 204 sub/big3
+ $ hg commit -m"remove x bit from sub/big3"
+ $ hg update -r3
+ 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ hg bfupdate -v
+ 1 big files updated, 0 removed
+ $ $PYTHON $TESTDIR/lsmode.py sub/big3
+ 100707 204 sub/big3
+ $ hg update -r4
+ 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ hg bfupdate -v
+ 1 big files updated, 0 removed
+ $ $PYTHON $TESTDIR/lsmode.py sub/big3
+ 100606 204 sub/big3
+ $ umask $old
More information about the Mercurial-devel
mailing list