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