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