##// END OF EJS Templates
largefiles: don't create chain of __contains__ calls...
Martin von Zweigbergk -
r24287:f7825242 default
parent child Browse files
Show More
@@ -1,374 +1,375 b''
1 # Copyright 2009-2010 Gregory P. Ward
1 # Copyright 2009-2010 Gregory P. Ward
2 # Copyright 2009-2010 Intelerad Medical Systems Incorporated
2 # Copyright 2009-2010 Intelerad Medical Systems Incorporated
3 # Copyright 2010-2011 Fog Creek Software
3 # Copyright 2010-2011 Fog Creek Software
4 # Copyright 2010-2011 Unity Technologies
4 # Copyright 2010-2011 Unity Technologies
5 #
5 #
6 # This software may be used and distributed according to the terms of the
6 # This software may be used and distributed according to the terms of the
7 # GNU General Public License version 2 or any later version.
7 # GNU General Public License version 2 or any later version.
8
8
9 '''setup for largefiles repositories: reposetup'''
9 '''setup for largefiles repositories: reposetup'''
10 import copy
10 import copy
11 import os
11 import os
12
12
13 from mercurial import error, match as match_, util
13 from mercurial import error, match as match_, util
14 from mercurial.i18n import _
14 from mercurial.i18n import _
15 from mercurial import scmutil, localrepo
15 from mercurial import scmutil, localrepo
16
16
17 import lfcommands
17 import lfcommands
18 import lfutil
18 import lfutil
19
19
20 def reposetup(ui, repo):
20 def reposetup(ui, repo):
21 # wire repositories should be given new wireproto functions
21 # wire repositories should be given new wireproto functions
22 # by "proto.wirereposetup()" via "hg.wirepeersetupfuncs"
22 # by "proto.wirereposetup()" via "hg.wirepeersetupfuncs"
23 if not repo.local():
23 if not repo.local():
24 return
24 return
25
25
26 class lfilesrepo(repo.__class__):
26 class lfilesrepo(repo.__class__):
27 # the mark to examine whether "repo" object enables largefiles or not
27 # the mark to examine whether "repo" object enables largefiles or not
28 _largefilesenabled = True
28 _largefilesenabled = True
29
29
30 lfstatus = False
30 lfstatus = False
31 def status_nolfiles(self, *args, **kwargs):
31 def status_nolfiles(self, *args, **kwargs):
32 return super(lfilesrepo, self).status(*args, **kwargs)
32 return super(lfilesrepo, self).status(*args, **kwargs)
33
33
34 # When lfstatus is set, return a context that gives the names
34 # When lfstatus is set, return a context that gives the names
35 # of largefiles instead of their corresponding standins and
35 # of largefiles instead of their corresponding standins and
36 # identifies the largefiles as always binary, regardless of
36 # identifies the largefiles as always binary, regardless of
37 # their actual contents.
37 # their actual contents.
38 def __getitem__(self, changeid):
38 def __getitem__(self, changeid):
39 ctx = super(lfilesrepo, self).__getitem__(changeid)
39 ctx = super(lfilesrepo, self).__getitem__(changeid)
40 if self.lfstatus:
40 if self.lfstatus:
41 class lfilesctx(ctx.__class__):
41 class lfilesctx(ctx.__class__):
42 def files(self):
42 def files(self):
43 filenames = super(lfilesctx, self).files()
43 filenames = super(lfilesctx, self).files()
44 return [lfutil.splitstandin(f) or f for f in filenames]
44 return [lfutil.splitstandin(f) or f for f in filenames]
45 def manifest(self):
45 def manifest(self):
46 man1 = super(lfilesctx, self).manifest()
46 man1 = super(lfilesctx, self).manifest()
47 orig = man1.__contains__
47 class lfilesmanifest(man1.__class):
48 def __contains__(self, filename):
48 def __contains__(self, filename):
49 return (orig(filename) or
49 orig = super(lfilesmanifest, self).__contains__
50 orig(lfutil.standin(filename)))
50 return (orig(filename) or
51 man1.__contains__ = __contains__.__get__(man1)
51 orig(lfutil.standin(filename)))
52 man1.__class__ = lfilesmanifest
52 return man1
53 return man1
53 def filectx(self, path, fileid=None, filelog=None):
54 def filectx(self, path, fileid=None, filelog=None):
54 orig = super(lfilesctx, self).filectx
55 orig = super(lfilesctx, self).filectx
55 try:
56 try:
56 if filelog is not None:
57 if filelog is not None:
57 result = orig(path, fileid, filelog)
58 result = orig(path, fileid, filelog)
58 else:
59 else:
59 result = orig(path, fileid)
60 result = orig(path, fileid)
60 except error.LookupError:
61 except error.LookupError:
61 # Adding a null character will cause Mercurial to
62 # Adding a null character will cause Mercurial to
62 # identify this as a binary file.
63 # identify this as a binary file.
63 if filelog is not None:
64 if filelog is not None:
64 result = orig(lfutil.standin(path), fileid,
65 result = orig(lfutil.standin(path), fileid,
65 filelog)
66 filelog)
66 else:
67 else:
67 result = orig(lfutil.standin(path), fileid)
68 result = orig(lfutil.standin(path), fileid)
68 olddata = result.data
69 olddata = result.data
69 result.data = lambda: olddata() + '\0'
70 result.data = lambda: olddata() + '\0'
70 return result
71 return result
71 ctx.__class__ = lfilesctx
72 ctx.__class__ = lfilesctx
72 return ctx
73 return ctx
73
74
74 # Figure out the status of big files and insert them into the
75 # Figure out the status of big files and insert them into the
75 # appropriate list in the result. Also removes standin files
76 # appropriate list in the result. Also removes standin files
76 # from the listing. Revert to the original status if
77 # from the listing. Revert to the original status if
77 # self.lfstatus is False.
78 # self.lfstatus is False.
78 # XXX large file status is buggy when used on repo proxy.
79 # XXX large file status is buggy when used on repo proxy.
79 # XXX this needs to be investigated.
80 # XXX this needs to be investigated.
80 @localrepo.unfilteredmethod
81 @localrepo.unfilteredmethod
81 def status(self, node1='.', node2=None, match=None, ignored=False,
82 def status(self, node1='.', node2=None, match=None, ignored=False,
82 clean=False, unknown=False, listsubrepos=False):
83 clean=False, unknown=False, listsubrepos=False):
83 listignored, listclean, listunknown = ignored, clean, unknown
84 listignored, listclean, listunknown = ignored, clean, unknown
84 orig = super(lfilesrepo, self).status
85 orig = super(lfilesrepo, self).status
85 if not self.lfstatus:
86 if not self.lfstatus:
86 return orig(node1, node2, match, listignored, listclean,
87 return orig(node1, node2, match, listignored, listclean,
87 listunknown, listsubrepos)
88 listunknown, listsubrepos)
88
89
89 # some calls in this function rely on the old version of status
90 # some calls in this function rely on the old version of status
90 self.lfstatus = False
91 self.lfstatus = False
91 ctx1 = self[node1]
92 ctx1 = self[node1]
92 ctx2 = self[node2]
93 ctx2 = self[node2]
93 working = ctx2.rev() is None
94 working = ctx2.rev() is None
94 parentworking = working and ctx1 == self['.']
95 parentworking = working and ctx1 == self['.']
95
96
96 if match is None:
97 if match is None:
97 match = match_.always(self.root, self.getcwd())
98 match = match_.always(self.root, self.getcwd())
98
99
99 wlock = None
100 wlock = None
100 try:
101 try:
101 try:
102 try:
102 # updating the dirstate is optional
103 # updating the dirstate is optional
103 # so we don't wait on the lock
104 # so we don't wait on the lock
104 wlock = self.wlock(False)
105 wlock = self.wlock(False)
105 except error.LockError:
106 except error.LockError:
106 pass
107 pass
107
108
108 # First check if paths or patterns were specified on the
109 # First check if paths or patterns were specified on the
109 # command line. If there were, and they don't match any
110 # command line. If there were, and they don't match any
110 # largefiles, we should just bail here and let super
111 # largefiles, we should just bail here and let super
111 # handle it -- thus gaining a big performance boost.
112 # handle it -- thus gaining a big performance boost.
112 lfdirstate = lfutil.openlfdirstate(ui, self)
113 lfdirstate = lfutil.openlfdirstate(ui, self)
113 if not match.always():
114 if not match.always():
114 for f in lfdirstate:
115 for f in lfdirstate:
115 if match(f):
116 if match(f):
116 break
117 break
117 else:
118 else:
118 return orig(node1, node2, match, listignored, listclean,
119 return orig(node1, node2, match, listignored, listclean,
119 listunknown, listsubrepos)
120 listunknown, listsubrepos)
120
121
121 # Create a copy of match that matches standins instead
122 # Create a copy of match that matches standins instead
122 # of largefiles.
123 # of largefiles.
123 def tostandins(files):
124 def tostandins(files):
124 if not working:
125 if not working:
125 return files
126 return files
126 newfiles = []
127 newfiles = []
127 dirstate = self.dirstate
128 dirstate = self.dirstate
128 for f in files:
129 for f in files:
129 sf = lfutil.standin(f)
130 sf = lfutil.standin(f)
130 if sf in dirstate:
131 if sf in dirstate:
131 newfiles.append(sf)
132 newfiles.append(sf)
132 elif sf in dirstate.dirs():
133 elif sf in dirstate.dirs():
133 # Directory entries could be regular or
134 # Directory entries could be regular or
134 # standin, check both
135 # standin, check both
135 newfiles.extend((f, sf))
136 newfiles.extend((f, sf))
136 else:
137 else:
137 newfiles.append(f)
138 newfiles.append(f)
138 return newfiles
139 return newfiles
139
140
140 m = copy.copy(match)
141 m = copy.copy(match)
141 m._files = tostandins(m._files)
142 m._files = tostandins(m._files)
142
143
143 result = orig(node1, node2, m, ignored, clean, unknown,
144 result = orig(node1, node2, m, ignored, clean, unknown,
144 listsubrepos)
145 listsubrepos)
145 if working:
146 if working:
146
147
147 def sfindirstate(f):
148 def sfindirstate(f):
148 sf = lfutil.standin(f)
149 sf = lfutil.standin(f)
149 dirstate = self.dirstate
150 dirstate = self.dirstate
150 return sf in dirstate or sf in dirstate.dirs()
151 return sf in dirstate or sf in dirstate.dirs()
151
152
152 match._files = [f for f in match._files
153 match._files = [f for f in match._files
153 if sfindirstate(f)]
154 if sfindirstate(f)]
154 # Don't waste time getting the ignored and unknown
155 # Don't waste time getting the ignored and unknown
155 # files from lfdirstate
156 # files from lfdirstate
156 unsure, s = lfdirstate.status(match, [], False, listclean,
157 unsure, s = lfdirstate.status(match, [], False, listclean,
157 False)
158 False)
158 (modified, added, removed, clean) = (s.modified, s.added,
159 (modified, added, removed, clean) = (s.modified, s.added,
159 s.removed, s.clean)
160 s.removed, s.clean)
160 if parentworking:
161 if parentworking:
161 for lfile in unsure:
162 for lfile in unsure:
162 standin = lfutil.standin(lfile)
163 standin = lfutil.standin(lfile)
163 if standin not in ctx1:
164 if standin not in ctx1:
164 # from second parent
165 # from second parent
165 modified.append(lfile)
166 modified.append(lfile)
166 elif ctx1[standin].data().strip() \
167 elif ctx1[standin].data().strip() \
167 != lfutil.hashfile(self.wjoin(lfile)):
168 != lfutil.hashfile(self.wjoin(lfile)):
168 modified.append(lfile)
169 modified.append(lfile)
169 else:
170 else:
170 if listclean:
171 if listclean:
171 clean.append(lfile)
172 clean.append(lfile)
172 lfdirstate.normal(lfile)
173 lfdirstate.normal(lfile)
173 else:
174 else:
174 tocheck = unsure + modified + added + clean
175 tocheck = unsure + modified + added + clean
175 modified, added, clean = [], [], []
176 modified, added, clean = [], [], []
176 checkexec = self.dirstate._checkexec
177 checkexec = self.dirstate._checkexec
177
178
178 for lfile in tocheck:
179 for lfile in tocheck:
179 standin = lfutil.standin(lfile)
180 standin = lfutil.standin(lfile)
180 if standin in ctx1:
181 if standin in ctx1:
181 abslfile = self.wjoin(lfile)
182 abslfile = self.wjoin(lfile)
182 if ((ctx1[standin].data().strip() !=
183 if ((ctx1[standin].data().strip() !=
183 lfutil.hashfile(abslfile)) or
184 lfutil.hashfile(abslfile)) or
184 (checkexec and
185 (checkexec and
185 ('x' in ctx1.flags(standin)) !=
186 ('x' in ctx1.flags(standin)) !=
186 bool(lfutil.getexecutable(abslfile)))):
187 bool(lfutil.getexecutable(abslfile)))):
187 modified.append(lfile)
188 modified.append(lfile)
188 elif listclean:
189 elif listclean:
189 clean.append(lfile)
190 clean.append(lfile)
190 else:
191 else:
191 added.append(lfile)
192 added.append(lfile)
192
193
193 # at this point, 'removed' contains largefiles
194 # at this point, 'removed' contains largefiles
194 # marked as 'R' in the working context.
195 # marked as 'R' in the working context.
195 # then, largefiles not managed also in the target
196 # then, largefiles not managed also in the target
196 # context should be excluded from 'removed'.
197 # context should be excluded from 'removed'.
197 removed = [lfile for lfile in removed
198 removed = [lfile for lfile in removed
198 if lfutil.standin(lfile) in ctx1]
199 if lfutil.standin(lfile) in ctx1]
199
200
200 # Standins no longer found in lfdirstate has been
201 # Standins no longer found in lfdirstate has been
201 # removed
202 # removed
202 for standin in ctx1.walk(lfutil.getstandinmatcher(self)):
203 for standin in ctx1.walk(lfutil.getstandinmatcher(self)):
203 lfile = lfutil.splitstandin(standin)
204 lfile = lfutil.splitstandin(standin)
204 if not match(lfile):
205 if not match(lfile):
205 continue
206 continue
206 if lfile not in lfdirstate:
207 if lfile not in lfdirstate:
207 removed.append(lfile)
208 removed.append(lfile)
208
209
209 # Filter result lists
210 # Filter result lists
210 result = list(result)
211 result = list(result)
211
212
212 # Largefiles are not really removed when they're
213 # Largefiles are not really removed when they're
213 # still in the normal dirstate. Likewise, normal
214 # still in the normal dirstate. Likewise, normal
214 # files are not really removed if they are still in
215 # files are not really removed if they are still in
215 # lfdirstate. This happens in merges where files
216 # lfdirstate. This happens in merges where files
216 # change type.
217 # change type.
217 removed = [f for f in removed
218 removed = [f for f in removed
218 if f not in self.dirstate]
219 if f not in self.dirstate]
219 result[2] = [f for f in result[2]
220 result[2] = [f for f in result[2]
220 if f not in lfdirstate]
221 if f not in lfdirstate]
221
222
222 lfiles = set(lfdirstate._map)
223 lfiles = set(lfdirstate._map)
223 # Unknown files
224 # Unknown files
224 result[4] = set(result[4]).difference(lfiles)
225 result[4] = set(result[4]).difference(lfiles)
225 # Ignored files
226 # Ignored files
226 result[5] = set(result[5]).difference(lfiles)
227 result[5] = set(result[5]).difference(lfiles)
227 # combine normal files and largefiles
228 # combine normal files and largefiles
228 normals = [[fn for fn in filelist
229 normals = [[fn for fn in filelist
229 if not lfutil.isstandin(fn)]
230 if not lfutil.isstandin(fn)]
230 for filelist in result]
231 for filelist in result]
231 lfstatus = (modified, added, removed, s.deleted, [], [],
232 lfstatus = (modified, added, removed, s.deleted, [], [],
232 clean)
233 clean)
233 result = [sorted(list1 + list2)
234 result = [sorted(list1 + list2)
234 for (list1, list2) in zip(normals, lfstatus)]
235 for (list1, list2) in zip(normals, lfstatus)]
235 else: # not against working directory
236 else: # not against working directory
236 result = [[lfutil.splitstandin(f) or f for f in items]
237 result = [[lfutil.splitstandin(f) or f for f in items]
237 for items in result]
238 for items in result]
238
239
239 if wlock:
240 if wlock:
240 lfdirstate.write()
241 lfdirstate.write()
241
242
242 finally:
243 finally:
243 if wlock:
244 if wlock:
244 wlock.release()
245 wlock.release()
245
246
246 self.lfstatus = True
247 self.lfstatus = True
247 return scmutil.status(*result)
248 return scmutil.status(*result)
248
249
249 def commitctx(self, ctx, *args, **kwargs):
250 def commitctx(self, ctx, *args, **kwargs):
250 node = super(lfilesrepo, self).commitctx(ctx, *args, **kwargs)
251 node = super(lfilesrepo, self).commitctx(ctx, *args, **kwargs)
251 class lfilesctx(ctx.__class__):
252 class lfilesctx(ctx.__class__):
252 def markcommitted(self, node):
253 def markcommitted(self, node):
253 orig = super(lfilesctx, self).markcommitted
254 orig = super(lfilesctx, self).markcommitted
254 return lfutil.markcommitted(orig, self, node)
255 return lfutil.markcommitted(orig, self, node)
255 ctx.__class__ = lfilesctx
256 ctx.__class__ = lfilesctx
256 return node
257 return node
257
258
258 # Before commit, largefile standins have not had their
259 # Before commit, largefile standins have not had their
259 # contents updated to reflect the hash of their largefile.
260 # contents updated to reflect the hash of their largefile.
260 # Do that here.
261 # Do that here.
261 def commit(self, text="", user=None, date=None, match=None,
262 def commit(self, text="", user=None, date=None, match=None,
262 force=False, editor=False, extra={}):
263 force=False, editor=False, extra={}):
263 orig = super(lfilesrepo, self).commit
264 orig = super(lfilesrepo, self).commit
264
265
265 wlock = self.wlock()
266 wlock = self.wlock()
266 try:
267 try:
267 lfcommithook = self._lfcommithooks[-1]
268 lfcommithook = self._lfcommithooks[-1]
268 match = lfcommithook(self, match)
269 match = lfcommithook(self, match)
269 result = orig(text=text, user=user, date=date, match=match,
270 result = orig(text=text, user=user, date=date, match=match,
270 force=force, editor=editor, extra=extra)
271 force=force, editor=editor, extra=extra)
271 return result
272 return result
272 finally:
273 finally:
273 wlock.release()
274 wlock.release()
274
275
275 def push(self, remote, force=False, revs=None, newbranch=False):
276 def push(self, remote, force=False, revs=None, newbranch=False):
276 if remote.local():
277 if remote.local():
277 missing = set(self.requirements) - remote.local().supported
278 missing = set(self.requirements) - remote.local().supported
278 if missing:
279 if missing:
279 msg = _("required features are not"
280 msg = _("required features are not"
280 " supported in the destination:"
281 " supported in the destination:"
281 " %s") % (', '.join(sorted(missing)))
282 " %s") % (', '.join(sorted(missing)))
282 raise util.Abort(msg)
283 raise util.Abort(msg)
283 return super(lfilesrepo, self).push(remote, force=force, revs=revs,
284 return super(lfilesrepo, self).push(remote, force=force, revs=revs,
284 newbranch=newbranch)
285 newbranch=newbranch)
285
286
286 # TODO: _subdirlfs should be moved into "lfutil.py", because
287 # TODO: _subdirlfs should be moved into "lfutil.py", because
287 # it is referred only from "lfutil.updatestandinsbymatch"
288 # it is referred only from "lfutil.updatestandinsbymatch"
288 def _subdirlfs(self, files, lfiles):
289 def _subdirlfs(self, files, lfiles):
289 '''
290 '''
290 Adjust matched file list
291 Adjust matched file list
291 If we pass a directory to commit whose only committable files
292 If we pass a directory to commit whose only committable files
292 are largefiles, the core commit code aborts before finding
293 are largefiles, the core commit code aborts before finding
293 the largefiles.
294 the largefiles.
294 So we do the following:
295 So we do the following:
295 For directories that only have largefiles as matches,
296 For directories that only have largefiles as matches,
296 we explicitly add the largefiles to the match list and remove
297 we explicitly add the largefiles to the match list and remove
297 the directory.
298 the directory.
298 In other cases, we leave the match list unmodified.
299 In other cases, we leave the match list unmodified.
299 '''
300 '''
300 actualfiles = []
301 actualfiles = []
301 dirs = []
302 dirs = []
302 regulars = []
303 regulars = []
303
304
304 for f in files:
305 for f in files:
305 if lfutil.isstandin(f + '/'):
306 if lfutil.isstandin(f + '/'):
306 raise util.Abort(
307 raise util.Abort(
307 _('file "%s" is a largefile standin') % f,
308 _('file "%s" is a largefile standin') % f,
308 hint=('commit the largefile itself instead'))
309 hint=('commit the largefile itself instead'))
309 # Scan directories
310 # Scan directories
310 if os.path.isdir(self.wjoin(f)):
311 if os.path.isdir(self.wjoin(f)):
311 dirs.append(f)
312 dirs.append(f)
312 else:
313 else:
313 regulars.append(f)
314 regulars.append(f)
314
315
315 for f in dirs:
316 for f in dirs:
316 matcheddir = False
317 matcheddir = False
317 d = self.dirstate.normalize(f) + '/'
318 d = self.dirstate.normalize(f) + '/'
318 # Check for matched normal files
319 # Check for matched normal files
319 for mf in regulars:
320 for mf in regulars:
320 if self.dirstate.normalize(mf).startswith(d):
321 if self.dirstate.normalize(mf).startswith(d):
321 actualfiles.append(f)
322 actualfiles.append(f)
322 matcheddir = True
323 matcheddir = True
323 break
324 break
324 if not matcheddir:
325 if not matcheddir:
325 # If no normal match, manually append
326 # If no normal match, manually append
326 # any matching largefiles
327 # any matching largefiles
327 for lf in lfiles:
328 for lf in lfiles:
328 if self.dirstate.normalize(lf).startswith(d):
329 if self.dirstate.normalize(lf).startswith(d):
329 actualfiles.append(lf)
330 actualfiles.append(lf)
330 if not matcheddir:
331 if not matcheddir:
331 # There may still be normal files in the dir, so
332 # There may still be normal files in the dir, so
332 # add a directory to the list, which
333 # add a directory to the list, which
333 # forces status/dirstate to walk all files and
334 # forces status/dirstate to walk all files and
334 # call the match function on the matcher, even
335 # call the match function on the matcher, even
335 # on case sensitive filesystems.
336 # on case sensitive filesystems.
336 actualfiles.append('.')
337 actualfiles.append('.')
337 matcheddir = True
338 matcheddir = True
338 # Nothing in dir, so readd it
339 # Nothing in dir, so readd it
339 # and let commit reject it
340 # and let commit reject it
340 if not matcheddir:
341 if not matcheddir:
341 actualfiles.append(f)
342 actualfiles.append(f)
342
343
343 # Always add normal files
344 # Always add normal files
344 actualfiles += regulars
345 actualfiles += regulars
345 return actualfiles
346 return actualfiles
346
347
347 repo.__class__ = lfilesrepo
348 repo.__class__ = lfilesrepo
348
349
349 # stack of hooks being executed before committing.
350 # stack of hooks being executed before committing.
350 # only last element ("_lfcommithooks[-1]") is used for each committing.
351 # only last element ("_lfcommithooks[-1]") is used for each committing.
351 repo._lfcommithooks = [lfutil.updatestandinsbymatch]
352 repo._lfcommithooks = [lfutil.updatestandinsbymatch]
352
353
353 # Stack of status writer functions taking "*msg, **opts" arguments
354 # Stack of status writer functions taking "*msg, **opts" arguments
354 # like "ui.status()". Only last element ("_lfstatuswriters[-1]")
355 # like "ui.status()". Only last element ("_lfstatuswriters[-1]")
355 # is used to write status out.
356 # is used to write status out.
356 repo._lfstatuswriters = [ui.status]
357 repo._lfstatuswriters = [ui.status]
357
358
358 def prepushoutgoinghook(local, remote, outgoing):
359 def prepushoutgoinghook(local, remote, outgoing):
359 if outgoing.missing:
360 if outgoing.missing:
360 toupload = set()
361 toupload = set()
361 addfunc = lambda fn, lfhash: toupload.add(lfhash)
362 addfunc = lambda fn, lfhash: toupload.add(lfhash)
362 lfutil.getlfilestoupload(local, outgoing.missing, addfunc)
363 lfutil.getlfilestoupload(local, outgoing.missing, addfunc)
363 lfcommands.uploadlfiles(ui, local, remote, toupload)
364 lfcommands.uploadlfiles(ui, local, remote, toupload)
364 repo.prepushoutgoinghooks.add("largefiles", prepushoutgoinghook)
365 repo.prepushoutgoinghooks.add("largefiles", prepushoutgoinghook)
365
366
366 def checkrequireslfiles(ui, repo, **kwargs):
367 def checkrequireslfiles(ui, repo, **kwargs):
367 if 'largefiles' not in repo.requirements and util.any(
368 if 'largefiles' not in repo.requirements and util.any(
368 lfutil.shortname+'/' in f[0] for f in repo.store.datafiles()):
369 lfutil.shortname+'/' in f[0] for f in repo.store.datafiles()):
369 repo.requirements.add('largefiles')
370 repo.requirements.add('largefiles')
370 repo._writerequirements()
371 repo._writerequirements()
371
372
372 ui.setconfig('hooks', 'changegroup.lfiles', checkrequireslfiles,
373 ui.setconfig('hooks', 'changegroup.lfiles', checkrequireslfiles,
373 'largefiles')
374 'largefiles')
374 ui.setconfig('hooks', 'commit.lfiles', checkrequireslfiles, 'largefiles')
375 ui.setconfig('hooks', 'commit.lfiles', checkrequireslfiles, 'largefiles')
General Comments 0
You need to be logged in to leave comments. Login now