annotate hgext/largefiles/basestore.py @ 15252:6e809bb4f969

largefiles: improve comments, internal docstrings - fix some ungrammatical/unclear/incorrect comments/docstrings - rewrite some really unclear comments/docstrings - make formatting/style more consistent with the rest of Mercurial (lowercase without period unless it's really multiple sentences) - wrap to 75 columns - always say "largefile(s)", not "lfile(s)" (or "big files") - one space between sentences, not two
author Greg Ward <greg@gerg.ca>
date Wed, 12 Oct 2011 20:59:27 -0400
parents aa262fff87ac
children 67d010779907
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
1 # Copyright 2009-2010 Gregory P. Ward
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
2 # Copyright 2009-2010 Intelerad Medical Systems Incorporated
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
3 # Copyright 2010-2011 Fog Creek Software
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
4 # Copyright 2010-2011 Unity Technologies
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
5 #
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
6 # This software may be used and distributed according to the terms of the
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
7 # GNU General Public License version 2 or any later version.
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
8
15252
6e809bb4f969 largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents: 15169
diff changeset
9 '''base class for store implementations and store-related utility code'''
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
10
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
11 import os
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
12 import tempfile
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
13 import binascii
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
14 import re
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
15
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
16 from mercurial import util, node, hg
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
17 from mercurial.i18n import _
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
18
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
19 import lfutil
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
20
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
21 class StoreError(Exception):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
22 '''Raised when there is a problem getting files from or putting
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
23 files to a central store.'''
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
24 def __init__(self, filename, hash, url, detail):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
25 self.filename = filename
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
26 self.hash = hash
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
27 self.url = url
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
28 self.detail = detail
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
29
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
30 def longmessage(self):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
31 if self.url:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
32 return ('%s: %s\n'
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
33 '(failed URL: %s)\n'
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
34 % (self.filename, self.detail, self.url))
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
35 else:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
36 return ('%s: %s\n'
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
37 '(no default or default-push path set in hgrc)\n'
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
38 % (self.filename, self.detail))
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
39
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
40 def __str__(self):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
41 return "%s: %s" % (self.url, self.detail)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
42
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
43 class basestore(object):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
44 def __init__(self, ui, repo, url):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
45 self.ui = ui
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
46 self.repo = repo
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
47 self.url = url
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
48
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
49 def put(self, source, hash):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
50 '''Put source file into the store under <filename>/<hash>.'''
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
51 raise NotImplementedError('abstract method')
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
52
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
53 def exists(self, hash):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
54 '''Check to see if the store contains the given hash.'''
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
55 raise NotImplementedError('abstract method')
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
56
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
57 def get(self, files):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
58 '''Get the specified largefiles from the store and write to local
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
59 files under repo.root. files is a list of (filename, hash)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
60 tuples. Return (success, missing), lists of files successfuly
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
61 downloaded and those not found in the store. success is a list
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
62 of (filename, hash) tuples; missing is a list of filenames that
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
63 we could not get. (The detailed error message will already have
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
64 been presented to the user, so missing is just supplied as a
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
65 summary.)'''
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
66 success = []
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
67 missing = []
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
68 ui = self.ui
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
69
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
70 at = 0
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
71 for filename, hash in files:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
72 ui.progress(_('getting largefiles'), at, unit='lfile',
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
73 total=len(files))
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
74 at += 1
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
75 ui.note(_('getting %s:%s\n') % (filename, hash))
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
76
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
77 cachefilename = lfutil.cachepath(self.repo, hash)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
78 cachedir = os.path.dirname(cachefilename)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
79
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
80 # No need to pass mode='wb' to fdopen(), since mkstemp() already
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
81 # opened the file in binary mode.
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
82 (tmpfd, tmpfilename) = tempfile.mkstemp(
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
83 dir=cachedir, prefix=os.path.basename(filename))
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
84 tmpfile = os.fdopen(tmpfd, 'w')
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
85
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
86 try:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
87 hhash = binascii.hexlify(self._getfile(tmpfile, filename, hash))
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
88 except StoreError, err:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
89 ui.warn(err.longmessage())
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
90 hhash = ""
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
91
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
92 if hhash != hash:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
93 if hhash != "":
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
94 ui.warn(_('%s: data corruption (expected %s, got %s)\n')
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
95 % (filename, hash, hhash))
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
96 tmpfile.close() # no-op if it's already closed
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
97 os.remove(tmpfilename)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
98 missing.append(filename)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
99 continue
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
100
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
101 if os.path.exists(cachefilename): # Windows
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
102 os.remove(cachefilename)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
103 os.rename(tmpfilename, cachefilename)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
104 lfutil.linktosystemcache(self.repo, hash)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
105 success.append((filename, hhash))
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
106
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
107 ui.progress(_('getting largefiles'), None)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
108 return (success, missing)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
109
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
110 def verify(self, revs, contents=False):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
111 '''Verify the existence (and, optionally, contents) of every big
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
112 file revision referenced by every changeset in revs.
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
113 Return 0 if all is well, non-zero on any errors.'''
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
114 write = self.ui.write
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
115 failed = False
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
116
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
117 write(_('searching %d changesets for largefiles\n') % len(revs))
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
118 verified = set() # set of (filename, filenode) tuples
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
119
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
120 for rev in revs:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
121 cctx = self.repo[rev]
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
122 cset = "%d:%s" % (cctx.rev(), node.short(cctx.node()))
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
123
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
124 failed = lfutil.any_(self._verifyfile(
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
125 cctx, cset, contents, standin, verified) for standin in cctx)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
126
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
127 num_revs = len(verified)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
128 num_lfiles = len(set([fname for (fname, fnode) in verified]))
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
129 if contents:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
130 write(_('verified contents of %d revisions of %d largefiles\n')
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
131 % (num_revs, num_lfiles))
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
132 else:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
133 write(_('verified existence of %d revisions of %d largefiles\n')
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
134 % (num_revs, num_lfiles))
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
135
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
136 return int(failed)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
137
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
138 def _getfile(self, tmpfile, filename, hash):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
139 '''Fetch one revision of one file from the store and write it
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
140 to tmpfile. Compute the hash of the file on-the-fly as it
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
141 downloads and return the binary hash. Close tmpfile. Raise
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
142 StoreError if unable to download the file (e.g. it does not
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
143 exist in the store).'''
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
144 raise NotImplementedError('abstract method')
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
145
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
146 def _verifyfile(self, cctx, cset, contents, standin, verified):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
147 '''Perform the actual verification of a file in the store.
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
148 '''
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
149 raise NotImplementedError('abstract method')
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
150
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
151 import localstore, wirestore
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
152
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
153 _storeprovider = {
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
154 'file': [localstore.localstore],
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
155 'http': [wirestore.wirestore],
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
156 'https': [wirestore.wirestore],
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
157 'ssh': [wirestore.wirestore],
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
158 }
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
159
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
160 _scheme_re = re.compile(r'^([a-zA-Z0-9+-.]+)://')
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
161
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
162 # During clone this function is passed the src's ui object
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
163 # but it needs the dest's ui object so it can read out of
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
164 # the config file. Use repo.ui instead.
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
165 def _openstore(repo, remote=None, put=False):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
166 ui = repo.ui
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
167
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
168 if not remote:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
169 path = getattr(repo, 'lfpullsource', None) or \
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
170 ui.expandpath('default-push', 'default')
15252
6e809bb4f969 largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents: 15169
diff changeset
171
6e809bb4f969 largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents: 15169
diff changeset
172 # ui.expandpath() leaves 'default-push' and 'default' alone if
6e809bb4f969 largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents: 15169
diff changeset
173 # they cannot be expanded: fallback to the empty string,
6e809bb4f969 largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents: 15169
diff changeset
174 # meaning the current directory.
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
175 if path == 'default-push' or path == 'default':
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
176 path = ''
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
177 remote = repo
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
178 else:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
179 remote = hg.peer(repo, {}, path)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
180
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
181 # The path could be a scheme so use Mercurial's normal functionality
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
182 # to resolve the scheme to a repository and use its path
15169
aa262fff87ac largefile: fix up hasattr usage
Matt Mackall <mpm@selenic.com>
parents: 15168
diff changeset
183 path = util.safehasattr(remote, 'url') and remote.url() or remote.path
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
184
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
185 match = _scheme_re.match(path)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
186 if not match: # regular filesystem path
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
187 scheme = 'file'
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
188 else:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
189 scheme = match.group(1)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
190
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
191 try:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
192 storeproviders = _storeprovider[scheme]
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
193 except KeyError:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
194 raise util.Abort(_('unsupported URL scheme %r') % scheme)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
195
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
196 for class_obj in storeproviders:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
197 try:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
198 return class_obj(ui, repo, remote)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
199 except lfutil.storeprotonotcapable:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
200 pass
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
201
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
202 raise util.Abort(_('%s does not appear to be a lfile store'), path)