[PATCH 2 of 4 bfiles] sshstore: implement sshstore's verify method

david.douard at logilab.fr david.douard at logilab.fr
Tue Dec 1 13:05:11 CST 2009


# HG changeset patch
# User David Douard <david.douard at logilab.fr>
# Date 1259691358 -3600
# Node ID cae8ee45627db044f7c8375165e7e0738dc6d74a
# Parent  1fc6ddc898b5ef990440a66dfc92d940c7897a1f
sshstore: implement sshstore's verify method

diff --git a/bfiles.py b/bfiles.py
--- a/bfiles.py
+++ b/bfiles.py
@@ -1009,9 +1009,6 @@
             # remote may send "unsynced changes"
             self.abort(error.RepoError(_("put failed: %s") % r))
 
-    def verify(self, revs, contents=False):
-        raise NotImplementedError('abstract method')
-
     def _getfile(self, tmpfile, filename, hash):
         storefile = os.path.join(self.path, filename, hash)
         hasher = hashlib.sha1()
@@ -1037,6 +1034,45 @@
                 break
             yield data
 
+    def _verifyfile(self, cctx, cset, contents, standin, verified):
+        filename = _split_standin(standin)
+        if not filename:
+            return False
+        fctx = cctx[standin]
+        key = (filename, fctx.filenode())
+        if key in verified:
+            return False
+
+        expect_hash = fctx.data()[0:40]
+        store_path = os.path.join(self.path, filename, expect_hash)
+        verified.add(key)
+
+        self.do_cmd("bfexists", destname=store_path)
+        r = self._recv()
+        if r not in ('ok', ''):
+            self.abort(error.RepoError(_("check failed, unexpected response: %s") % r))
+        if not r:
+            self.ui.warn(
+                _('changeset %s: %s missing\n'
+                  '  (%s)\n')
+                % (cset, filename, store_path))
+            return True                 # failed
+
+        if contents:
+            self.do_cmd("bfverify", destname=store_path)
+            r = self._recv()
+            if r not in ('ok', ''):
+                self.abort(error.RepoError(_("check failed, unexpected response: %s") % r))
+            if not r:
+                self.ui.warn(
+                    _('changeset %s: %s: contents differ\n'
+                      '  (%s)\n')
+                    % (cset, filename,
+                       store_path))
+                return True             # failed
+        return False
+
+
     # XXX *snip* method heavily based on sshrepository.validate_repo
     def validate_connection(self, ui, sshcmd, args, remotecmd):
         # cleanup up previous run
@@ -1262,6 +1298,35 @@
         finally:
             fd.close()
 
+    def do_bfexists(self):
+        """respond to the bfexists command: check a file exists
+        """
+        key, fname = self.getarg()
+        if os.path.isfile(fname):
+            self.respond('ok')
+        else:
+            self.respond('')
+
+    def do_bfverify(self):
+        """respond to the bfhash command: check the hash of the file match its name
+        """
+        key, fname = self.getarg()
+        if not os.path.isfile(fname):
+            self.respond('file %s does not exists' % fname)
+            return
+        try:
+            fd = open(fname, "rb")
+        except IOError:
+            self.respond('cannot read file')
+            return
+        hhash = _hashfile(fd)
+        fd.close()
+        expect_hash = os.path.basename(fname)
+        if expect_hash == hhash:
+            self.respond('ok')
+        else:
+            self.respond('')
+
 # -- hg commands declarations ------------------------------------------------
 
 commands.norepo += " bfserve"


More information about the Mercurial-devel mailing list