##// END OF EJS Templates
largefiles: use lfutil functions...
Martin Geisler -
r15628:2b405133 default
parent child Browse files
Show More
@@ -1,425 +1,422 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 types
11 import types
12 import os
12 import os
13 import re
14
13
15 from mercurial import context, error, manifest, match as match_, node, util
14 from mercurial import context, error, manifest, match as match_, node, util
16 from mercurial.i18n import _
15 from mercurial.i18n import _
17
16
18 import lfcommands
17 import lfcommands
19 import proto
18 import proto
20 import lfutil
19 import lfutil
21
20
22 def reposetup(ui, repo):
21 def reposetup(ui, repo):
23 # wire repositories should be given new wireproto functions but not the
22 # wire repositories should be given new wireproto functions but not the
24 # other largefiles modifications
23 # other largefiles modifications
25 if not repo.local():
24 if not repo.local():
26 return proto.wirereposetup(ui, repo)
25 return proto.wirereposetup(ui, repo)
27
26
28 for name in ('status', 'commitctx', 'commit', 'push'):
27 for name in ('status', 'commitctx', 'commit', 'push'):
29 method = getattr(repo, name)
28 method = getattr(repo, name)
30 #if not (isinstance(method, types.MethodType) and
29 #if not (isinstance(method, types.MethodType) and
31 # method.im_func is repo.__class__.commitctx.im_func):
30 # method.im_func is repo.__class__.commitctx.im_func):
32 if (isinstance(method, types.FunctionType) and
31 if (isinstance(method, types.FunctionType) and
33 method.func_name == 'wrap'):
32 method.func_name == 'wrap'):
34 ui.warn(_('largefiles: repo method %r appears to have already been'
33 ui.warn(_('largefiles: repo method %r appears to have already been'
35 ' wrapped by another extension: '
34 ' wrapped by another extension: '
36 'largefiles may behave incorrectly\n')
35 'largefiles may behave incorrectly\n')
37 % name)
36 % name)
38
37
39 class lfiles_repo(repo.__class__):
38 class lfiles_repo(repo.__class__):
40 lfstatus = False
39 lfstatus = False
41 def status_nolfiles(self, *args, **kwargs):
40 def status_nolfiles(self, *args, **kwargs):
42 return super(lfiles_repo, self).status(*args, **kwargs)
41 return super(lfiles_repo, self).status(*args, **kwargs)
43
42
44 # When lfstatus is set, return a context that gives the names
43 # When lfstatus is set, return a context that gives the names
45 # of largefiles instead of their corresponding standins and
44 # of largefiles instead of their corresponding standins and
46 # identifies the largefiles as always binary, regardless of
45 # identifies the largefiles as always binary, regardless of
47 # their actual contents.
46 # their actual contents.
48 def __getitem__(self, changeid):
47 def __getitem__(self, changeid):
49 ctx = super(lfiles_repo, self).__getitem__(changeid)
48 ctx = super(lfiles_repo, self).__getitem__(changeid)
50 if self.lfstatus:
49 if self.lfstatus:
51 class lfiles_manifestdict(manifest.manifestdict):
50 class lfiles_manifestdict(manifest.manifestdict):
52 def __contains__(self, filename):
51 def __contains__(self, filename):
53 if super(lfiles_manifestdict,
52 if super(lfiles_manifestdict,
54 self).__contains__(filename):
53 self).__contains__(filename):
55 return True
54 return True
56 return super(lfiles_manifestdict,
55 return super(lfiles_manifestdict,
57 self).__contains__(lfutil.shortname+'/' + filename)
56 self).__contains__(lfutil.standin(filename))
58 class lfiles_ctx(ctx.__class__):
57 class lfiles_ctx(ctx.__class__):
59 def files(self):
58 def files(self):
60 filenames = super(lfiles_ctx, self).files()
59 filenames = super(lfiles_ctx, self).files()
61 return [re.sub('^\\'+lfutil.shortname+'/', '',
60 return [lfutil.splitstandin(f) or f for f in filenames]
62 filename) for filename in filenames]
63 def manifest(self):
61 def manifest(self):
64 man1 = super(lfiles_ctx, self).manifest()
62 man1 = super(lfiles_ctx, self).manifest()
65 man1.__class__ = lfiles_manifestdict
63 man1.__class__ = lfiles_manifestdict
66 return man1
64 return man1
67 def filectx(self, path, fileid=None, filelog=None):
65 def filectx(self, path, fileid=None, filelog=None):
68 try:
66 try:
69 result = super(lfiles_ctx, self).filectx(path,
67 result = super(lfiles_ctx, self).filectx(path,
70 fileid, filelog)
68 fileid, filelog)
71 except error.LookupError:
69 except error.LookupError:
72 # Adding a null character will cause Mercurial to
70 # Adding a null character will cause Mercurial to
73 # identify this as a binary file.
71 # identify this as a binary file.
74 result = super(lfiles_ctx, self).filectx(
72 result = super(lfiles_ctx, self).filectx(
75 lfutil.shortname + '/' + path, fileid,
73 lfutil.standin(path), fileid, filelog)
76 filelog)
77 olddata = result.data
74 olddata = result.data
78 result.data = lambda: olddata() + '\0'
75 result.data = lambda: olddata() + '\0'
79 return result
76 return result
80 ctx.__class__ = lfiles_ctx
77 ctx.__class__ = lfiles_ctx
81 return ctx
78 return ctx
82
79
83 # Figure out the status of big files and insert them into the
80 # Figure out the status of big files and insert them into the
84 # appropriate list in the result. Also removes standin files
81 # appropriate list in the result. Also removes standin files
85 # from the listing. Revert to the original status if
82 # from the listing. Revert to the original status if
86 # self.lfstatus is False.
83 # self.lfstatus is False.
87 def status(self, node1='.', node2=None, match=None, ignored=False,
84 def status(self, node1='.', node2=None, match=None, ignored=False,
88 clean=False, unknown=False, listsubrepos=False):
85 clean=False, unknown=False, listsubrepos=False):
89 listignored, listclean, listunknown = ignored, clean, unknown
86 listignored, listclean, listunknown = ignored, clean, unknown
90 if not self.lfstatus:
87 if not self.lfstatus:
91 return super(lfiles_repo, self).status(node1, node2, match,
88 return super(lfiles_repo, self).status(node1, node2, match,
92 listignored, listclean, listunknown, listsubrepos)
89 listignored, listclean, listunknown, listsubrepos)
93 else:
90 else:
94 # some calls in this function rely on the old version of status
91 # some calls in this function rely on the old version of status
95 self.lfstatus = False
92 self.lfstatus = False
96 if isinstance(node1, context.changectx):
93 if isinstance(node1, context.changectx):
97 ctx1 = node1
94 ctx1 = node1
98 else:
95 else:
99 ctx1 = repo[node1]
96 ctx1 = repo[node1]
100 if isinstance(node2, context.changectx):
97 if isinstance(node2, context.changectx):
101 ctx2 = node2
98 ctx2 = node2
102 else:
99 else:
103 ctx2 = repo[node2]
100 ctx2 = repo[node2]
104 working = ctx2.rev() is None
101 working = ctx2.rev() is None
105 parentworking = working and ctx1 == self['.']
102 parentworking = working and ctx1 == self['.']
106
103
107 def inctx(file, ctx):
104 def inctx(file, ctx):
108 try:
105 try:
109 if ctx.rev() is None:
106 if ctx.rev() is None:
110 return file in ctx.manifest()
107 return file in ctx.manifest()
111 ctx[file]
108 ctx[file]
112 return True
109 return True
113 except KeyError:
110 except KeyError:
114 return False
111 return False
115
112
116 if match is None:
113 if match is None:
117 match = match_.always(self.root, self.getcwd())
114 match = match_.always(self.root, self.getcwd())
118
115
119 # Create a copy of match that matches standins instead
116 # Create a copy of match that matches standins instead
120 # of largefiles.
117 # of largefiles.
121 def tostandin(file):
118 def tostandin(file):
122 if inctx(lfutil.standin(file), ctx2):
119 if inctx(lfutil.standin(file), ctx2):
123 return lfutil.standin(file)
120 return lfutil.standin(file)
124 return file
121 return file
125
122
126 # Create a function that we can use to override what is
123 # Create a function that we can use to override what is
127 # normally the ignore matcher. We've already checked
124 # normally the ignore matcher. We've already checked
128 # for ignored files on the first dirstate walk, and
125 # for ignored files on the first dirstate walk, and
129 # unecessarily re-checking here causes a huge performance
126 # unecessarily re-checking here causes a huge performance
130 # hit because lfdirstate only knows about largefiles
127 # hit because lfdirstate only knows about largefiles
131 def _ignoreoverride(self):
128 def _ignoreoverride(self):
132 return False
129 return False
133
130
134 m = copy.copy(match)
131 m = copy.copy(match)
135 m._files = [tostandin(f) for f in m._files]
132 m._files = [tostandin(f) for f in m._files]
136
133
137 # Get ignored files here even if we weren't asked for them; we
134 # Get ignored files here even if we weren't asked for them; we
138 # must use the result here for filtering later
135 # must use the result here for filtering later
139 result = super(lfiles_repo, self).status(node1, node2, m,
136 result = super(lfiles_repo, self).status(node1, node2, m,
140 True, clean, unknown, listsubrepos)
137 True, clean, unknown, listsubrepos)
141 if working:
138 if working:
142 # hold the wlock while we read largefiles and
139 # hold the wlock while we read largefiles and
143 # update the lfdirstate
140 # update the lfdirstate
144 wlock = repo.wlock()
141 wlock = repo.wlock()
145 try:
142 try:
146 # Any non-largefiles that were explicitly listed must be
143 # Any non-largefiles that were explicitly listed must be
147 # taken out or lfdirstate.status will report an error.
144 # taken out or lfdirstate.status will report an error.
148 # The status of these files was already computed using
145 # The status of these files was already computed using
149 # super's status.
146 # super's status.
150 lfdirstate = lfutil.openlfdirstate(ui, self)
147 lfdirstate = lfutil.openlfdirstate(ui, self)
151 # Override lfdirstate's ignore matcher to not do
148 # Override lfdirstate's ignore matcher to not do
152 # anything
149 # anything
153 orig_ignore = lfdirstate._ignore
150 orig_ignore = lfdirstate._ignore
154 lfdirstate._ignore = _ignoreoverride
151 lfdirstate._ignore = _ignoreoverride
155
152
156 match._files = [f for f in match._files if f in
153 match._files = [f for f in match._files if f in
157 lfdirstate]
154 lfdirstate]
158 # Don't waste time getting the ignored and unknown
155 # Don't waste time getting the ignored and unknown
159 # files again; we already have them
156 # files again; we already have them
160 s = lfdirstate.status(match, [], False,
157 s = lfdirstate.status(match, [], False,
161 listclean, False)
158 listclean, False)
162 (unsure, modified, added, removed, missing, unknown,
159 (unsure, modified, added, removed, missing, unknown,
163 ignored, clean) = s
160 ignored, clean) = s
164 # Replace the list of ignored and unknown files with
161 # Replace the list of ignored and unknown files with
165 # the previously caclulated lists, and strip out the
162 # the previously caclulated lists, and strip out the
166 # largefiles
163 # largefiles
167 lfiles = set(lfdirstate._map)
164 lfiles = set(lfdirstate._map)
168 ignored = set(result[5]).difference(lfiles)
165 ignored = set(result[5]).difference(lfiles)
169 unknown = set(result[4]).difference(lfiles)
166 unknown = set(result[4]).difference(lfiles)
170 if parentworking:
167 if parentworking:
171 for lfile in unsure:
168 for lfile in unsure:
172 if ctx1[lfutil.standin(lfile)].data().strip() \
169 if ctx1[lfutil.standin(lfile)].data().strip() \
173 != lfutil.hashfile(self.wjoin(lfile)):
170 != lfutil.hashfile(self.wjoin(lfile)):
174 modified.append(lfile)
171 modified.append(lfile)
175 else:
172 else:
176 clean.append(lfile)
173 clean.append(lfile)
177 lfdirstate.normal(lfile)
174 lfdirstate.normal(lfile)
178 lfdirstate.write()
175 lfdirstate.write()
179 else:
176 else:
180 tocheck = unsure + modified + added + clean
177 tocheck = unsure + modified + added + clean
181 modified, added, clean = [], [], []
178 modified, added, clean = [], [], []
182
179
183 for lfile in tocheck:
180 for lfile in tocheck:
184 standin = lfutil.standin(lfile)
181 standin = lfutil.standin(lfile)
185 if inctx(standin, ctx1):
182 if inctx(standin, ctx1):
186 if ctx1[standin].data().strip() != \
183 if ctx1[standin].data().strip() != \
187 lfutil.hashfile(self.wjoin(lfile)):
184 lfutil.hashfile(self.wjoin(lfile)):
188 modified.append(lfile)
185 modified.append(lfile)
189 else:
186 else:
190 clean.append(lfile)
187 clean.append(lfile)
191 else:
188 else:
192 added.append(lfile)
189 added.append(lfile)
193 # Replace the original ignore function
190 # Replace the original ignore function
194 lfdirstate._ignore = orig_ignore
191 lfdirstate._ignore = orig_ignore
195 finally:
192 finally:
196 wlock.release()
193 wlock.release()
197
194
198 for standin in ctx1.manifest():
195 for standin in ctx1.manifest():
199 if not lfutil.isstandin(standin):
196 if not lfutil.isstandin(standin):
200 continue
197 continue
201 lfile = lfutil.splitstandin(standin)
198 lfile = lfutil.splitstandin(standin)
202 if not match(lfile):
199 if not match(lfile):
203 continue
200 continue
204 if lfile not in lfdirstate:
201 if lfile not in lfdirstate:
205 removed.append(lfile)
202 removed.append(lfile)
206 # Handle unknown and ignored differently
203 # Handle unknown and ignored differently
207 lfiles = (modified, added, removed, missing, [], [], clean)
204 lfiles = (modified, added, removed, missing, [], [], clean)
208 result = list(result)
205 result = list(result)
209 # Unknown files
206 # Unknown files
210 unknown = set(unknown).difference(ignored)
207 unknown = set(unknown).difference(ignored)
211 result[4] = [f for f in unknown
208 result[4] = [f for f in unknown
212 if (repo.dirstate[f] == '?' and
209 if (repo.dirstate[f] == '?' and
213 not lfutil.isstandin(f))]
210 not lfutil.isstandin(f))]
214 # Ignored files were calculated earlier by the dirstate,
211 # Ignored files were calculated earlier by the dirstate,
215 # and we already stripped out the largefiles from the list
212 # and we already stripped out the largefiles from the list
216 result[5] = ignored
213 result[5] = ignored
217 # combine normal files and largefiles
214 # combine normal files and largefiles
218 normals = [[fn for fn in filelist
215 normals = [[fn for fn in filelist
219 if not lfutil.isstandin(fn)]
216 if not lfutil.isstandin(fn)]
220 for filelist in result]
217 for filelist in result]
221 result = [sorted(list1 + list2)
218 result = [sorted(list1 + list2)
222 for (list1, list2) in zip(normals, lfiles)]
219 for (list1, list2) in zip(normals, lfiles)]
223 else:
220 else:
224 def toname(f):
221 def toname(f):
225 if lfutil.isstandin(f):
222 if lfutil.isstandin(f):
226 return lfutil.splitstandin(f)
223 return lfutil.splitstandin(f)
227 return f
224 return f
228 result = [[toname(f) for f in items] for items in result]
225 result = [[toname(f) for f in items] for items in result]
229
226
230 if not listunknown:
227 if not listunknown:
231 result[4] = []
228 result[4] = []
232 if not listignored:
229 if not listignored:
233 result[5] = []
230 result[5] = []
234 if not listclean:
231 if not listclean:
235 result[6] = []
232 result[6] = []
236 self.lfstatus = True
233 self.lfstatus = True
237 return result
234 return result
238
235
239 # As part of committing, copy all of the largefiles into the
236 # As part of committing, copy all of the largefiles into the
240 # cache.
237 # cache.
241 def commitctx(self, *args, **kwargs):
238 def commitctx(self, *args, **kwargs):
242 node = super(lfiles_repo, self).commitctx(*args, **kwargs)
239 node = super(lfiles_repo, self).commitctx(*args, **kwargs)
243 ctx = self[node]
240 ctx = self[node]
244 for filename in ctx.files():
241 for filename in ctx.files():
245 if lfutil.isstandin(filename) and filename in ctx.manifest():
242 if lfutil.isstandin(filename) and filename in ctx.manifest():
246 realfile = lfutil.splitstandin(filename)
243 realfile = lfutil.splitstandin(filename)
247 lfutil.copytostore(self, ctx.node(), realfile)
244 lfutil.copytostore(self, ctx.node(), realfile)
248
245
249 return node
246 return node
250
247
251 # Before commit, largefile standins have not had their
248 # Before commit, largefile standins have not had their
252 # contents updated to reflect the hash of their largefile.
249 # contents updated to reflect the hash of their largefile.
253 # Do that here.
250 # Do that here.
254 def commit(self, text="", user=None, date=None, match=None,
251 def commit(self, text="", user=None, date=None, match=None,
255 force=False, editor=False, extra={}):
252 force=False, editor=False, extra={}):
256 orig = super(lfiles_repo, self).commit
253 orig = super(lfiles_repo, self).commit
257
254
258 wlock = repo.wlock()
255 wlock = repo.wlock()
259 try:
256 try:
260 if getattr(repo, "_isrebasing", False):
257 if getattr(repo, "_isrebasing", False):
261 # We have to take the time to pull down the new
258 # We have to take the time to pull down the new
262 # largefiles now. Otherwise if we are rebasing,
259 # largefiles now. Otherwise if we are rebasing,
263 # any largefiles that were modified in the
260 # any largefiles that were modified in the
264 # destination changesets get overwritten, either
261 # destination changesets get overwritten, either
265 # by the rebase or in the first commit after the
262 # by the rebase or in the first commit after the
266 # rebase.
263 # rebase.
267 lfcommands.updatelfiles(repo.ui, repo)
264 lfcommands.updatelfiles(repo.ui, repo)
268 # Case 1: user calls commit with no specific files or
265 # Case 1: user calls commit with no specific files or
269 # include/exclude patterns: refresh and commit all files that
266 # include/exclude patterns: refresh and commit all files that
270 # are "dirty".
267 # are "dirty".
271 if ((match is None) or
268 if ((match is None) or
272 (not match.anypats() and not match.files())):
269 (not match.anypats() and not match.files())):
273 # Spend a bit of time here to get a list of files we know
270 # Spend a bit of time here to get a list of files we know
274 # are modified so we can compare only against those.
271 # are modified so we can compare only against those.
275 # It can cost a lot of time (several seconds)
272 # It can cost a lot of time (several seconds)
276 # otherwise to update all standins if the largefiles are
273 # otherwise to update all standins if the largefiles are
277 # large.
274 # large.
278 lfdirstate = lfutil.openlfdirstate(ui, self)
275 lfdirstate = lfutil.openlfdirstate(ui, self)
279 dirtymatch = match_.always(repo.root, repo.getcwd())
276 dirtymatch = match_.always(repo.root, repo.getcwd())
280 s = lfdirstate.status(dirtymatch, [], False, False, False)
277 s = lfdirstate.status(dirtymatch, [], False, False, False)
281 modifiedfiles = []
278 modifiedfiles = []
282 for i in s:
279 for i in s:
283 modifiedfiles.extend(i)
280 modifiedfiles.extend(i)
284 lfiles = lfutil.listlfiles(self)
281 lfiles = lfutil.listlfiles(self)
285 # this only loops through largefiles that exist (not
282 # this only loops through largefiles that exist (not
286 # removed/renamed)
283 # removed/renamed)
287 for lfile in lfiles:
284 for lfile in lfiles:
288 if lfile in modifiedfiles:
285 if lfile in modifiedfiles:
289 if os.path.exists(self.wjoin(lfutil.standin(lfile))):
286 if os.path.exists(self.wjoin(lfutil.standin(lfile))):
290 # this handles the case where a rebase is being
287 # this handles the case where a rebase is being
291 # performed and the working copy is not updated
288 # performed and the working copy is not updated
292 # yet.
289 # yet.
293 if os.path.exists(self.wjoin(lfile)):
290 if os.path.exists(self.wjoin(lfile)):
294 lfutil.updatestandin(self,
291 lfutil.updatestandin(self,
295 lfutil.standin(lfile))
292 lfutil.standin(lfile))
296 lfdirstate.normal(lfile)
293 lfdirstate.normal(lfile)
297 for lfile in lfdirstate:
294 for lfile in lfdirstate:
298 if lfile in modifiedfiles:
295 if lfile in modifiedfiles:
299 if not os.path.exists(
296 if not os.path.exists(
300 repo.wjoin(lfutil.standin(lfile))):
297 repo.wjoin(lfutil.standin(lfile))):
301 lfdirstate.drop(lfile)
298 lfdirstate.drop(lfile)
302 lfdirstate.write()
299 lfdirstate.write()
303
300
304 return orig(text=text, user=user, date=date, match=match,
301 return orig(text=text, user=user, date=date, match=match,
305 force=force, editor=editor, extra=extra)
302 force=force, editor=editor, extra=extra)
306
303
307 for f in match.files():
304 for f in match.files():
308 if lfutil.isstandin(f):
305 if lfutil.isstandin(f):
309 raise util.Abort(
306 raise util.Abort(
310 _('file "%s" is a largefile standin') % f,
307 _('file "%s" is a largefile standin') % f,
311 hint=('commit the largefile itself instead'))
308 hint=('commit the largefile itself instead'))
312
309
313 # Case 2: user calls commit with specified patterns: refresh
310 # Case 2: user calls commit with specified patterns: refresh
314 # any matching big files.
311 # any matching big files.
315 smatcher = lfutil.composestandinmatcher(self, match)
312 smatcher = lfutil.composestandinmatcher(self, match)
316 standins = lfutil.dirstate_walk(self.dirstate, smatcher)
313 standins = lfutil.dirstate_walk(self.dirstate, smatcher)
317
314
318 # No matching big files: get out of the way and pass control to
315 # No matching big files: get out of the way and pass control to
319 # the usual commit() method.
316 # the usual commit() method.
320 if not standins:
317 if not standins:
321 return orig(text=text, user=user, date=date, match=match,
318 return orig(text=text, user=user, date=date, match=match,
322 force=force, editor=editor, extra=extra)
319 force=force, editor=editor, extra=extra)
323
320
324 # Refresh all matching big files. It's possible that the
321 # Refresh all matching big files. It's possible that the
325 # commit will end up failing, in which case the big files will
322 # commit will end up failing, in which case the big files will
326 # stay refreshed. No harm done: the user modified them and
323 # stay refreshed. No harm done: the user modified them and
327 # asked to commit them, so sooner or later we're going to
324 # asked to commit them, so sooner or later we're going to
328 # refresh the standins. Might as well leave them refreshed.
325 # refresh the standins. Might as well leave them refreshed.
329 lfdirstate = lfutil.openlfdirstate(ui, self)
326 lfdirstate = lfutil.openlfdirstate(ui, self)
330 for standin in standins:
327 for standin in standins:
331 lfile = lfutil.splitstandin(standin)
328 lfile = lfutil.splitstandin(standin)
332 if lfdirstate[lfile] <> 'r':
329 if lfdirstate[lfile] <> 'r':
333 lfutil.updatestandin(self, standin)
330 lfutil.updatestandin(self, standin)
334 lfdirstate.normal(lfile)
331 lfdirstate.normal(lfile)
335 else:
332 else:
336 lfdirstate.drop(lfile)
333 lfdirstate.drop(lfile)
337 lfdirstate.write()
334 lfdirstate.write()
338
335
339 # Cook up a new matcher that only matches regular files or
336 # Cook up a new matcher that only matches regular files or
340 # standins corresponding to the big files requested by the
337 # standins corresponding to the big files requested by the
341 # user. Have to modify _files to prevent commit() from
338 # user. Have to modify _files to prevent commit() from
342 # complaining "not tracked" for big files.
339 # complaining "not tracked" for big files.
343 lfiles = lfutil.listlfiles(repo)
340 lfiles = lfutil.listlfiles(repo)
344 match = copy.copy(match)
341 match = copy.copy(match)
345 orig_matchfn = match.matchfn
342 orig_matchfn = match.matchfn
346
343
347 # Check both the list of largefiles and the list of
344 # Check both the list of largefiles and the list of
348 # standins because if a largefile was removed, it
345 # standins because if a largefile was removed, it
349 # won't be in the list of largefiles at this point
346 # won't be in the list of largefiles at this point
350 match._files += sorted(standins)
347 match._files += sorted(standins)
351
348
352 actualfiles = []
349 actualfiles = []
353 for f in match._files:
350 for f in match._files:
354 fstandin = lfutil.standin(f)
351 fstandin = lfutil.standin(f)
355
352
356 # ignore known largefiles and standins
353 # ignore known largefiles and standins
357 if f in lfiles or fstandin in standins:
354 if f in lfiles or fstandin in standins:
358 continue
355 continue
359
356
360 # append directory separator to avoid collisions
357 # append directory separator to avoid collisions
361 if not fstandin.endswith(os.sep):
358 if not fstandin.endswith(os.sep):
362 fstandin += os.sep
359 fstandin += os.sep
363
360
364 # prevalidate matching standin directories
361 # prevalidate matching standin directories
365 if util.any(st for st in match._files
362 if util.any(st for st in match._files
366 if st.startswith(fstandin)):
363 if st.startswith(fstandin)):
367 continue
364 continue
368 actualfiles.append(f)
365 actualfiles.append(f)
369 match._files = actualfiles
366 match._files = actualfiles
370
367
371 def matchfn(f):
368 def matchfn(f):
372 if orig_matchfn(f):
369 if orig_matchfn(f):
373 return f not in lfiles
370 return f not in lfiles
374 else:
371 else:
375 return f in standins
372 return f in standins
376
373
377 match.matchfn = matchfn
374 match.matchfn = matchfn
378 return orig(text=text, user=user, date=date, match=match,
375 return orig(text=text, user=user, date=date, match=match,
379 force=force, editor=editor, extra=extra)
376 force=force, editor=editor, extra=extra)
380 finally:
377 finally:
381 wlock.release()
378 wlock.release()
382
379
383 def push(self, remote, force=False, revs=None, newbranch=False):
380 def push(self, remote, force=False, revs=None, newbranch=False):
384 o = lfutil.findoutgoing(repo, remote, force)
381 o = lfutil.findoutgoing(repo, remote, force)
385 if o:
382 if o:
386 toupload = set()
383 toupload = set()
387 o = repo.changelog.nodesbetween(o, revs)[0]
384 o = repo.changelog.nodesbetween(o, revs)[0]
388 for n in o:
385 for n in o:
389 parents = [p for p in repo.changelog.parents(n)
386 parents = [p for p in repo.changelog.parents(n)
390 if p != node.nullid]
387 if p != node.nullid]
391 ctx = repo[n]
388 ctx = repo[n]
392 files = set(ctx.files())
389 files = set(ctx.files())
393 if len(parents) == 2:
390 if len(parents) == 2:
394 mc = ctx.manifest()
391 mc = ctx.manifest()
395 mp1 = ctx.parents()[0].manifest()
392 mp1 = ctx.parents()[0].manifest()
396 mp2 = ctx.parents()[1].manifest()
393 mp2 = ctx.parents()[1].manifest()
397 for f in mp1:
394 for f in mp1:
398 if f not in mc:
395 if f not in mc:
399 files.add(f)
396 files.add(f)
400 for f in mp2:
397 for f in mp2:
401 if f not in mc:
398 if f not in mc:
402 files.add(f)
399 files.add(f)
403 for f in mc:
400 for f in mc:
404 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f,
401 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f,
405 None):
402 None):
406 files.add(f)
403 files.add(f)
407
404
408 toupload = toupload.union(
405 toupload = toupload.union(
409 set([ctx[f].data().strip()
406 set([ctx[f].data().strip()
410 for f in files
407 for f in files
411 if lfutil.isstandin(f) and f in ctx]))
408 if lfutil.isstandin(f) and f in ctx]))
412 lfcommands.uploadlfiles(ui, self, remote, toupload)
409 lfcommands.uploadlfiles(ui, self, remote, toupload)
413 return super(lfiles_repo, self).push(remote, force, revs,
410 return super(lfiles_repo, self).push(remote, force, revs,
414 newbranch)
411 newbranch)
415
412
416 repo.__class__ = lfiles_repo
413 repo.__class__ = lfiles_repo
417
414
418 def checkrequireslfiles(ui, repo, **kwargs):
415 def checkrequireslfiles(ui, repo, **kwargs):
419 if 'largefiles' not in repo.requirements and util.any(
416 if 'largefiles' not in repo.requirements and util.any(
420 lfutil.shortname+'/' in f[0] for f in repo.store.datafiles()):
417 lfutil.shortname+'/' in f[0] for f in repo.store.datafiles()):
421 repo.requirements.add('largefiles')
418 repo.requirements.add('largefiles')
422 repo._writerequirements()
419 repo._writerequirements()
423
420
424 ui.setconfig('hooks', 'changegroup.lfiles', checkrequireslfiles)
421 ui.setconfig('hooks', 'changegroup.lfiles', checkrequireslfiles)
425 ui.setconfig('hooks', 'commit.lfiles', checkrequireslfiles)
422 ui.setconfig('hooks', 'commit.lfiles', checkrequireslfiles)
General Comments 0
You need to be logged in to leave comments. Login now