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