Mercurial > hg
comparison hgext/lfs/blobstore.py @ 35477:bb6a80fc969a
lfs: only hardlink between the usercache and local store if the blob verifies
This fixes the issue where verify (and other read commands) would propagate
corrupt blobs. I originalled coded this to only hardlink if 'verify=True' for
store.read(), but then good blobs weren't being linked, and this broke a bunch
of tests. (The blob in repo5 that is being corrupted seems to be linked into
repo5 in the loop running dumpflog.py prior to it being corrupted, but only if
verify=False is handled too.) It's probably better to do a one time extra
verification in order to create these files, so that the repo can be copied to a
removable drive.
Adding the same check to store.write() was only for completeness, but also needs
to do a one time extra verification to avoid breaking tests.
author | Matt Harbison <matt_harbison@yahoo.com> |
---|---|
date | Thu, 21 Dec 2017 14:13:39 -0500 |
parents | 417e8e040102 |
children | 5a73a0446afd |
comparison
equal
deleted
inserted
replaced
35476:417e8e040102 | 35477:bb6a80fc969a |
---|---|
109 fp.write(data) | 109 fp.write(data) |
110 | 110 |
111 # XXX: should we verify the content of the cache, and hardlink back to | 111 # XXX: should we verify the content of the cache, and hardlink back to |
112 # the local store on success, but truncate, write and link on failure? | 112 # the local store on success, but truncate, write and link on failure? |
113 if not self.cachevfs.exists(oid): | 113 if not self.cachevfs.exists(oid): |
114 self.ui.note(_('lfs: adding %s to the usercache\n') % oid) | 114 if verify or hashlib.sha256(data).hexdigest() == oid: |
115 lfutil.link(self.vfs.join(oid), self.cachevfs.join(oid)) | 115 self.ui.note(_('lfs: adding %s to the usercache\n') % oid) |
116 lfutil.link(self.vfs.join(oid), self.cachevfs.join(oid)) | |
116 | 117 |
117 def read(self, oid, verify=True): | 118 def read(self, oid, verify=True): |
118 """Read blob from local blobstore.""" | 119 """Read blob from local blobstore.""" |
119 if not self.vfs.exists(oid): | 120 if not self.vfs.exists(oid): |
120 blob = self._read(self.cachevfs, oid, verify) | 121 blob = self._read(self.cachevfs, oid, verify) |
121 self.ui.note(_('lfs: found %s in the usercache\n') % oid) | 122 |
122 lfutil.link(self.cachevfs.join(oid), self.vfs.join(oid)) | 123 # Even if revlog will verify the content, it needs to be verified |
124 # now before making the hardlink to avoid propagating corrupt blobs. | |
125 # Don't abort if corruption is detected, because `hg verify` will | |
126 # give more useful info about the corruption- simply don't add the | |
127 # hardlink. | |
128 if verify or hashlib.sha256(blob).hexdigest() == oid: | |
129 self.ui.note(_('lfs: found %s in the usercache\n') % oid) | |
130 lfutil.link(self.cachevfs.join(oid), self.vfs.join(oid)) | |
123 else: | 131 else: |
124 self.ui.note(_('lfs: found %s in the local lfs store\n') % oid) | 132 self.ui.note(_('lfs: found %s in the local lfs store\n') % oid) |
125 blob = self._read(self.vfs, oid, verify) | 133 blob = self._read(self.vfs, oid, verify) |
126 return blob | 134 return blob |
127 | 135 |