##// END OF EJS Templates
largefiles: extract 'orig' method in reposetup.status
Martin von Zweigbergk -
r22518:52dd6e25 default
parent child Browse files
Show More
@@ -1,490 +1,490 b''
1 # Copyright 2009-2010 Gregory P. Ward
1 # Copyright 2009-2010 Gregory P. Ward
2 # Copyright 2009-2010 Intelerad Medical Systems Incorporated
2 # Copyright 2009-2010 Intelerad Medical Systems Incorporated
3 # Copyright 2010-2011 Fog Creek Software
3 # Copyright 2010-2011 Fog Creek Software
4 # Copyright 2010-2011 Unity Technologies
4 # Copyright 2010-2011 Unity Technologies
5 #
5 #
6 # This software may be used and distributed according to the terms of the
6 # This software may be used and distributed according to the terms of the
7 # GNU General Public License version 2 or any later version.
7 # GNU General Public License version 2 or any later version.
8
8
9 '''setup for largefiles repositories: reposetup'''
9 '''setup for largefiles repositories: reposetup'''
10 import copy
10 import copy
11 import os
11 import os
12
12
13 from mercurial import error, manifest, match as match_, util
13 from mercurial import error, manifest, match as match_, util
14 from mercurial.i18n import _
14 from mercurial.i18n import _
15 from mercurial import localrepo
15 from mercurial import localrepo
16
16
17 import lfcommands
17 import lfcommands
18 import lfutil
18 import lfutil
19
19
20 def reposetup(ui, repo):
20 def reposetup(ui, repo):
21 # wire repositories should be given new wireproto functions
21 # wire repositories should be given new wireproto functions
22 # by "proto.wirereposetup()" via "hg.wirepeersetupfuncs"
22 # by "proto.wirereposetup()" via "hg.wirepeersetupfuncs"
23 if not repo.local():
23 if not repo.local():
24 return
24 return
25
25
26 class lfilesrepo(repo.__class__):
26 class lfilesrepo(repo.__class__):
27 lfstatus = False
27 lfstatus = False
28 def status_nolfiles(self, *args, **kwargs):
28 def status_nolfiles(self, *args, **kwargs):
29 return super(lfilesrepo, self).status(*args, **kwargs)
29 return super(lfilesrepo, self).status(*args, **kwargs)
30
30
31 # When lfstatus is set, return a context that gives the names
31 # When lfstatus is set, return a context that gives the names
32 # of largefiles instead of their corresponding standins and
32 # of largefiles instead of their corresponding standins and
33 # identifies the largefiles as always binary, regardless of
33 # identifies the largefiles as always binary, regardless of
34 # their actual contents.
34 # their actual contents.
35 def __getitem__(self, changeid):
35 def __getitem__(self, changeid):
36 ctx = super(lfilesrepo, self).__getitem__(changeid)
36 ctx = super(lfilesrepo, self).__getitem__(changeid)
37 if self.lfstatus:
37 if self.lfstatus:
38 class lfilesmanifestdict(manifest.manifestdict):
38 class lfilesmanifestdict(manifest.manifestdict):
39 def __contains__(self, filename):
39 def __contains__(self, filename):
40 orig = super(lfilesmanifestdict, self).__contains__
40 orig = super(lfilesmanifestdict, self).__contains__
41 return orig(filename) or orig(lfutil.standin(filename))
41 return orig(filename) or orig(lfutil.standin(filename))
42 class lfilesctx(ctx.__class__):
42 class lfilesctx(ctx.__class__):
43 def files(self):
43 def files(self):
44 filenames = super(lfilesctx, self).files()
44 filenames = super(lfilesctx, self).files()
45 return [lfutil.splitstandin(f) or f for f in filenames]
45 return [lfutil.splitstandin(f) or f for f in filenames]
46 def manifest(self):
46 def manifest(self):
47 man1 = super(lfilesctx, self).manifest()
47 man1 = super(lfilesctx, self).manifest()
48 man1.__class__ = lfilesmanifestdict
48 man1.__class__ = lfilesmanifestdict
49 return man1
49 return man1
50 def filectx(self, path, fileid=None, filelog=None):
50 def filectx(self, path, fileid=None, filelog=None):
51 orig = super(lfilesctx, self).filectx
51 orig = super(lfilesctx, self).filectx
52 try:
52 try:
53 if filelog is not None:
53 if filelog is not None:
54 result = orig(path, fileid, filelog)
54 result = orig(path, fileid, filelog)
55 else:
55 else:
56 result = orig(path, fileid)
56 result = orig(path, fileid)
57 except error.LookupError:
57 except error.LookupError:
58 # Adding a null character will cause Mercurial to
58 # Adding a null character will cause Mercurial to
59 # identify this as a binary file.
59 # identify this as a binary file.
60 if filelog is not None:
60 if filelog is not None:
61 result = orig(lfutil.standin(path), fileid,
61 result = orig(lfutil.standin(path), fileid,
62 filelog)
62 filelog)
63 else:
63 else:
64 result = orig(lfutil.standin(path), fileid)
64 result = orig(lfutil.standin(path), fileid)
65 olddata = result.data
65 olddata = result.data
66 result.data = lambda: olddata() + '\0'
66 result.data = lambda: olddata() + '\0'
67 return result
67 return result
68 ctx.__class__ = lfilesctx
68 ctx.__class__ = lfilesctx
69 return ctx
69 return ctx
70
70
71 # Figure out the status of big files and insert them into the
71 # Figure out the status of big files and insert them into the
72 # appropriate list in the result. Also removes standin files
72 # appropriate list in the result. Also removes standin files
73 # from the listing. Revert to the original status if
73 # from the listing. Revert to the original status if
74 # self.lfstatus is False.
74 # self.lfstatus is False.
75 # XXX large file status is buggy when used on repo proxy.
75 # XXX large file status is buggy when used on repo proxy.
76 # XXX this needs to be investigated.
76 # XXX this needs to be investigated.
77 @localrepo.unfilteredmethod
77 @localrepo.unfilteredmethod
78 def status(self, node1='.', node2=None, match=None, ignored=False,
78 def status(self, node1='.', node2=None, match=None, ignored=False,
79 clean=False, unknown=False, listsubrepos=False):
79 clean=False, unknown=False, listsubrepos=False):
80 listignored, listclean, listunknown = ignored, clean, unknown
80 listignored, listclean, listunknown = ignored, clean, unknown
81 orig = super(lfilesrepo, self).status
81 if not self.lfstatus:
82 if not self.lfstatus:
82 return super(lfilesrepo, self).status(node1, node2, match,
83 return orig(node1, node2, match, listignored, listclean,
83 listignored, listclean, listunknown, listsubrepos)
84 listunknown, listsubrepos)
84
85
85 # some calls in this function rely on the old version of status
86 # some calls in this function rely on the old version of status
86 self.lfstatus = False
87 self.lfstatus = False
87 ctx1 = self[node1]
88 ctx1 = self[node1]
88 ctx2 = self[node2]
89 ctx2 = self[node2]
89 working = ctx2.rev() is None
90 working = ctx2.rev() is None
90 parentworking = working and ctx1 == self['.']
91 parentworking = working and ctx1 == self['.']
91
92
92 def inctx(file, ctx):
93 def inctx(file, ctx):
93 try:
94 try:
94 if ctx.rev() is None:
95 if ctx.rev() is None:
95 return file in ctx.manifest()
96 return file in ctx.manifest()
96 ctx[file]
97 ctx[file]
97 return True
98 return True
98 except KeyError:
99 except KeyError:
99 return False
100 return False
100
101
101 if match is None:
102 if match is None:
102 match = match_.always(self.root, self.getcwd())
103 match = match_.always(self.root, self.getcwd())
103
104
104 wlock = None
105 wlock = None
105 try:
106 try:
106 try:
107 try:
107 # updating the dirstate is optional
108 # updating the dirstate is optional
108 # so we don't wait on the lock
109 # so we don't wait on the lock
109 wlock = self.wlock(False)
110 wlock = self.wlock(False)
110 except error.LockError:
111 except error.LockError:
111 pass
112 pass
112
113
113 # First check if there were files specified on the
114 # First check if there were files specified on the
114 # command line. If there were, and none of them were
115 # command line. If there were, and none of them were
115 # largefiles, we should just bail here and let super
116 # largefiles, we should just bail here and let super
116 # handle it -- thus gaining a big performance boost.
117 # handle it -- thus gaining a big performance boost.
117 lfdirstate = lfutil.openlfdirstate(ui, self)
118 lfdirstate = lfutil.openlfdirstate(ui, self)
118 if match.files() and not match.anypats():
119 if match.files() and not match.anypats():
119 for f in lfdirstate:
120 for f in lfdirstate:
120 if match(f):
121 if match(f):
121 break
122 break
122 else:
123 else:
123 return super(lfilesrepo, self).status(node1, node2,
124 return orig(node1, node2, match, listignored, listclean,
124 match, listignored, listclean,
125 listunknown, listsubrepos)
125 listunknown, listsubrepos)
126
126
127 # Create a copy of match that matches standins instead
127 # Create a copy of match that matches standins instead
128 # of largefiles.
128 # of largefiles.
129 def tostandins(files):
129 def tostandins(files):
130 if not working:
130 if not working:
131 return files
131 return files
132 newfiles = []
132 newfiles = []
133 dirstate = self.dirstate
133 dirstate = self.dirstate
134 for f in files:
134 for f in files:
135 sf = lfutil.standin(f)
135 sf = lfutil.standin(f)
136 if sf in dirstate:
136 if sf in dirstate:
137 newfiles.append(sf)
137 newfiles.append(sf)
138 elif sf in dirstate.dirs():
138 elif sf in dirstate.dirs():
139 # Directory entries could be regular or
139 # Directory entries could be regular or
140 # standin, check both
140 # standin, check both
141 newfiles.extend((f, sf))
141 newfiles.extend((f, sf))
142 else:
142 else:
143 newfiles.append(f)
143 newfiles.append(f)
144 return newfiles
144 return newfiles
145
145
146 m = copy.copy(match)
146 m = copy.copy(match)
147 m._files = tostandins(m._files)
147 m._files = tostandins(m._files)
148
148
149 result = super(lfilesrepo, self).status(node1, node2, m,
149 result = orig(node1, node2, m, ignored, clean, unknown,
150 ignored, clean, unknown, listsubrepos)
150 listsubrepos)
151 if working:
151 if working:
152
152
153 def sfindirstate(f):
153 def sfindirstate(f):
154 sf = lfutil.standin(f)
154 sf = lfutil.standin(f)
155 dirstate = self.dirstate
155 dirstate = self.dirstate
156 return sf in dirstate or sf in dirstate.dirs()
156 return sf in dirstate or sf in dirstate.dirs()
157
157
158 match._files = [f for f in match._files
158 match._files = [f for f in match._files
159 if sfindirstate(f)]
159 if sfindirstate(f)]
160 # Don't waste time getting the ignored and unknown
160 # Don't waste time getting the ignored and unknown
161 # files from lfdirstate
161 # files from lfdirstate
162 s = lfdirstate.status(match, [], False,
162 s = lfdirstate.status(match, [], False,
163 listclean, False)
163 listclean, False)
164 (unsure, modified, added, removed, missing, _unknown,
164 (unsure, modified, added, removed, missing, _unknown,
165 _ignored, clean) = s
165 _ignored, clean) = s
166 if parentworking:
166 if parentworking:
167 for lfile in unsure:
167 for lfile in unsure:
168 standin = lfutil.standin(lfile)
168 standin = lfutil.standin(lfile)
169 if standin not in ctx1:
169 if standin not in ctx1:
170 # from second parent
170 # from second parent
171 modified.append(lfile)
171 modified.append(lfile)
172 elif ctx1[standin].data().strip() \
172 elif ctx1[standin].data().strip() \
173 != lfutil.hashfile(self.wjoin(lfile)):
173 != lfutil.hashfile(self.wjoin(lfile)):
174 modified.append(lfile)
174 modified.append(lfile)
175 else:
175 else:
176 clean.append(lfile)
176 clean.append(lfile)
177 lfdirstate.normal(lfile)
177 lfdirstate.normal(lfile)
178 else:
178 else:
179 tocheck = unsure + modified + added + clean
179 tocheck = unsure + modified + added + clean
180 modified, added, clean = [], [], []
180 modified, added, clean = [], [], []
181
181
182 for lfile in tocheck:
182 for lfile in tocheck:
183 standin = lfutil.standin(lfile)
183 standin = lfutil.standin(lfile)
184 if inctx(standin, ctx1):
184 if inctx(standin, ctx1):
185 if ctx1[standin].data().strip() != \
185 if ctx1[standin].data().strip() != \
186 lfutil.hashfile(self.wjoin(lfile)):
186 lfutil.hashfile(self.wjoin(lfile)):
187 modified.append(lfile)
187 modified.append(lfile)
188 else:
188 else:
189 clean.append(lfile)
189 clean.append(lfile)
190 else:
190 else:
191 added.append(lfile)
191 added.append(lfile)
192
192
193 # Standins no longer found in lfdirstate has been
193 # Standins no longer found in lfdirstate has been
194 # removed
194 # removed
195 for standin in ctx1.manifest():
195 for standin in ctx1.manifest():
196 if not lfutil.isstandin(standin):
196 if not lfutil.isstandin(standin):
197 continue
197 continue
198 lfile = lfutil.splitstandin(standin)
198 lfile = lfutil.splitstandin(standin)
199 if not match(lfile):
199 if not match(lfile):
200 continue
200 continue
201 if lfile not in lfdirstate:
201 if lfile not in lfdirstate:
202 removed.append(lfile)
202 removed.append(lfile)
203
203
204 # Filter result lists
204 # Filter result lists
205 result = list(result)
205 result = list(result)
206
206
207 # Largefiles are not really removed when they're
207 # Largefiles are not really removed when they're
208 # still in the normal dirstate. Likewise, normal
208 # still in the normal dirstate. Likewise, normal
209 # files are not really removed if they are still in
209 # files are not really removed if they are still in
210 # lfdirstate. This happens in merges where files
210 # lfdirstate. This happens in merges where files
211 # change type.
211 # change type.
212 removed = [f for f in removed
212 removed = [f for f in removed
213 if f not in self.dirstate]
213 if f not in self.dirstate]
214 result[2] = [f for f in result[2]
214 result[2] = [f for f in result[2]
215 if f not in lfdirstate]
215 if f not in lfdirstate]
216
216
217 lfiles = set(lfdirstate._map)
217 lfiles = set(lfdirstate._map)
218 # Unknown files
218 # Unknown files
219 result[4] = set(result[4]).difference(lfiles)
219 result[4] = set(result[4]).difference(lfiles)
220 # Ignored files
220 # Ignored files
221 result[5] = set(result[5]).difference(lfiles)
221 result[5] = set(result[5]).difference(lfiles)
222 # combine normal files and largefiles
222 # combine normal files and largefiles
223 normals = [[fn for fn in filelist
223 normals = [[fn for fn in filelist
224 if not lfutil.isstandin(fn)]
224 if not lfutil.isstandin(fn)]
225 for filelist in result]
225 for filelist in result]
226 lfiles = (modified, added, removed, missing, [], [], clean)
226 lfiles = (modified, added, removed, missing, [], [], clean)
227 result = [sorted(list1 + list2)
227 result = [sorted(list1 + list2)
228 for (list1, list2) in zip(normals, lfiles)]
228 for (list1, list2) in zip(normals, lfiles)]
229 else:
229 else:
230 def toname(f):
230 def toname(f):
231 if lfutil.isstandin(f):
231 if lfutil.isstandin(f):
232 return lfutil.splitstandin(f)
232 return lfutil.splitstandin(f)
233 return f
233 return f
234 result = [[toname(f) for f in items]
234 result = [[toname(f) for f in items]
235 for items in result]
235 for items in result]
236
236
237 if wlock:
237 if wlock:
238 lfdirstate.write()
238 lfdirstate.write()
239
239
240 finally:
240 finally:
241 if wlock:
241 if wlock:
242 wlock.release()
242 wlock.release()
243
243
244 if not listunknown:
244 if not listunknown:
245 result[4] = []
245 result[4] = []
246 if not listignored:
246 if not listignored:
247 result[5] = []
247 result[5] = []
248 if not listclean:
248 if not listclean:
249 result[6] = []
249 result[6] = []
250 self.lfstatus = True
250 self.lfstatus = True
251 return result
251 return result
252
252
253 # As part of committing, copy all of the largefiles into the
253 # As part of committing, copy all of the largefiles into the
254 # cache.
254 # cache.
255 def commitctx(self, *args, **kwargs):
255 def commitctx(self, *args, **kwargs):
256 node = super(lfilesrepo, self).commitctx(*args, **kwargs)
256 node = super(lfilesrepo, self).commitctx(*args, **kwargs)
257 lfutil.copyalltostore(self, node)
257 lfutil.copyalltostore(self, node)
258 return node
258 return node
259
259
260 # Before commit, largefile standins have not had their
260 # Before commit, largefile standins have not had their
261 # contents updated to reflect the hash of their largefile.
261 # contents updated to reflect the hash of their largefile.
262 # Do that here.
262 # Do that here.
263 def commit(self, text="", user=None, date=None, match=None,
263 def commit(self, text="", user=None, date=None, match=None,
264 force=False, editor=False, extra={}):
264 force=False, editor=False, extra={}):
265 orig = super(lfilesrepo, self).commit
265 orig = super(lfilesrepo, self).commit
266
266
267 wlock = self.wlock()
267 wlock = self.wlock()
268 try:
268 try:
269 # Case 0: Automated committing
269 # Case 0: Automated committing
270 #
270 #
271 # While automated committing (like rebase, transplant
271 # While automated committing (like rebase, transplant
272 # and so on), this code path is used to avoid:
272 # and so on), this code path is used to avoid:
273 # (1) updating standins, because standins should
273 # (1) updating standins, because standins should
274 # be already updated at this point
274 # be already updated at this point
275 # (2) aborting when stadnins are matched by "match",
275 # (2) aborting when stadnins are matched by "match",
276 # because automated committing may specify them directly
276 # because automated committing may specify them directly
277 #
277 #
278 if getattr(self, "_isrebasing", False) or \
278 if getattr(self, "_isrebasing", False) or \
279 getattr(self, "_istransplanting", False):
279 getattr(self, "_istransplanting", False):
280 result = orig(text=text, user=user, date=date, match=match,
280 result = orig(text=text, user=user, date=date, match=match,
281 force=force, editor=editor, extra=extra)
281 force=force, editor=editor, extra=extra)
282
282
283 if result:
283 if result:
284 lfdirstate = lfutil.openlfdirstate(ui, self)
284 lfdirstate = lfutil.openlfdirstate(ui, self)
285 for f in self[result].files():
285 for f in self[result].files():
286 if lfutil.isstandin(f):
286 if lfutil.isstandin(f):
287 lfile = lfutil.splitstandin(f)
287 lfile = lfutil.splitstandin(f)
288 lfutil.synclfdirstate(self, lfdirstate, lfile,
288 lfutil.synclfdirstate(self, lfdirstate, lfile,
289 False)
289 False)
290 lfdirstate.write()
290 lfdirstate.write()
291
291
292 return result
292 return result
293 # Case 1: user calls commit with no specific files or
293 # Case 1: user calls commit with no specific files or
294 # include/exclude patterns: refresh and commit all files that
294 # include/exclude patterns: refresh and commit all files that
295 # are "dirty".
295 # are "dirty".
296 if ((match is None) or
296 if ((match is None) or
297 (not match.anypats() and not match.files())):
297 (not match.anypats() and not match.files())):
298 # Spend a bit of time here to get a list of files we know
298 # Spend a bit of time here to get a list of files we know
299 # are modified so we can compare only against those.
299 # are modified so we can compare only against those.
300 # It can cost a lot of time (several seconds)
300 # It can cost a lot of time (several seconds)
301 # otherwise to update all standins if the largefiles are
301 # otherwise to update all standins if the largefiles are
302 # large.
302 # large.
303 lfdirstate = lfutil.openlfdirstate(ui, self)
303 lfdirstate = lfutil.openlfdirstate(ui, self)
304 dirtymatch = match_.always(self.root, self.getcwd())
304 dirtymatch = match_.always(self.root, self.getcwd())
305 s = lfdirstate.status(dirtymatch, [], False, False, False)
305 s = lfdirstate.status(dirtymatch, [], False, False, False)
306 (unsure, modified, added, removed, _missing, _unknown,
306 (unsure, modified, added, removed, _missing, _unknown,
307 _ignored, _clean) = s
307 _ignored, _clean) = s
308 modifiedfiles = unsure + modified + added + removed
308 modifiedfiles = unsure + modified + added + removed
309 lfiles = lfutil.listlfiles(self)
309 lfiles = lfutil.listlfiles(self)
310 # this only loops through largefiles that exist (not
310 # this only loops through largefiles that exist (not
311 # removed/renamed)
311 # removed/renamed)
312 for lfile in lfiles:
312 for lfile in lfiles:
313 if lfile in modifiedfiles:
313 if lfile in modifiedfiles:
314 if os.path.exists(
314 if os.path.exists(
315 self.wjoin(lfutil.standin(lfile))):
315 self.wjoin(lfutil.standin(lfile))):
316 # this handles the case where a rebase is being
316 # this handles the case where a rebase is being
317 # performed and the working copy is not updated
317 # performed and the working copy is not updated
318 # yet.
318 # yet.
319 if os.path.exists(self.wjoin(lfile)):
319 if os.path.exists(self.wjoin(lfile)):
320 lfutil.updatestandin(self,
320 lfutil.updatestandin(self,
321 lfutil.standin(lfile))
321 lfutil.standin(lfile))
322 lfdirstate.normal(lfile)
322 lfdirstate.normal(lfile)
323
323
324 result = orig(text=text, user=user, date=date, match=match,
324 result = orig(text=text, user=user, date=date, match=match,
325 force=force, editor=editor, extra=extra)
325 force=force, editor=editor, extra=extra)
326
326
327 if result is not None:
327 if result is not None:
328 for lfile in lfdirstate:
328 for lfile in lfdirstate:
329 if lfile in modifiedfiles:
329 if lfile in modifiedfiles:
330 if (not os.path.exists(self.wjoin(
330 if (not os.path.exists(self.wjoin(
331 lfutil.standin(lfile)))) or \
331 lfutil.standin(lfile)))) or \
332 (not os.path.exists(self.wjoin(lfile))):
332 (not os.path.exists(self.wjoin(lfile))):
333 lfdirstate.drop(lfile)
333 lfdirstate.drop(lfile)
334
334
335 # This needs to be after commit; otherwise precommit hooks
335 # This needs to be after commit; otherwise precommit hooks
336 # get the wrong status
336 # get the wrong status
337 lfdirstate.write()
337 lfdirstate.write()
338 return result
338 return result
339
339
340 lfiles = lfutil.listlfiles(self)
340 lfiles = lfutil.listlfiles(self)
341 match._files = self._subdirlfs(match.files(), lfiles)
341 match._files = self._subdirlfs(match.files(), lfiles)
342
342
343 # Case 2: user calls commit with specified patterns: refresh
343 # Case 2: user calls commit with specified patterns: refresh
344 # any matching big files.
344 # any matching big files.
345 smatcher = lfutil.composestandinmatcher(self, match)
345 smatcher = lfutil.composestandinmatcher(self, match)
346 standins = self.dirstate.walk(smatcher, [], False, False)
346 standins = self.dirstate.walk(smatcher, [], False, False)
347
347
348 # No matching big files: get out of the way and pass control to
348 # No matching big files: get out of the way and pass control to
349 # the usual commit() method.
349 # the usual commit() method.
350 if not standins:
350 if not standins:
351 return orig(text=text, user=user, date=date, match=match,
351 return orig(text=text, user=user, date=date, match=match,
352 force=force, editor=editor, extra=extra)
352 force=force, editor=editor, extra=extra)
353
353
354 # Refresh all matching big files. It's possible that the
354 # Refresh all matching big files. It's possible that the
355 # commit will end up failing, in which case the big files will
355 # commit will end up failing, in which case the big files will
356 # stay refreshed. No harm done: the user modified them and
356 # stay refreshed. No harm done: the user modified them and
357 # asked to commit them, so sooner or later we're going to
357 # asked to commit them, so sooner or later we're going to
358 # refresh the standins. Might as well leave them refreshed.
358 # refresh the standins. Might as well leave them refreshed.
359 lfdirstate = lfutil.openlfdirstate(ui, self)
359 lfdirstate = lfutil.openlfdirstate(ui, self)
360 for standin in standins:
360 for standin in standins:
361 lfile = lfutil.splitstandin(standin)
361 lfile = lfutil.splitstandin(standin)
362 if lfdirstate[lfile] != 'r':
362 if lfdirstate[lfile] != 'r':
363 lfutil.updatestandin(self, standin)
363 lfutil.updatestandin(self, standin)
364 lfdirstate.normal(lfile)
364 lfdirstate.normal(lfile)
365 else:
365 else:
366 lfdirstate.drop(lfile)
366 lfdirstate.drop(lfile)
367
367
368 # Cook up a new matcher that only matches regular files or
368 # Cook up a new matcher that only matches regular files or
369 # standins corresponding to the big files requested by the
369 # standins corresponding to the big files requested by the
370 # user. Have to modify _files to prevent commit() from
370 # user. Have to modify _files to prevent commit() from
371 # complaining "not tracked" for big files.
371 # complaining "not tracked" for big files.
372 match = copy.copy(match)
372 match = copy.copy(match)
373 origmatchfn = match.matchfn
373 origmatchfn = match.matchfn
374
374
375 # Check both the list of largefiles and the list of
375 # Check both the list of largefiles and the list of
376 # standins because if a largefile was removed, it
376 # standins because if a largefile was removed, it
377 # won't be in the list of largefiles at this point
377 # won't be in the list of largefiles at this point
378 match._files += sorted(standins)
378 match._files += sorted(standins)
379
379
380 actualfiles = []
380 actualfiles = []
381 for f in match._files:
381 for f in match._files:
382 fstandin = lfutil.standin(f)
382 fstandin = lfutil.standin(f)
383
383
384 # ignore known largefiles and standins
384 # ignore known largefiles and standins
385 if f in lfiles or fstandin in standins:
385 if f in lfiles or fstandin in standins:
386 continue
386 continue
387
387
388 actualfiles.append(f)
388 actualfiles.append(f)
389 match._files = actualfiles
389 match._files = actualfiles
390
390
391 def matchfn(f):
391 def matchfn(f):
392 if origmatchfn(f):
392 if origmatchfn(f):
393 return f not in lfiles
393 return f not in lfiles
394 else:
394 else:
395 return f in standins
395 return f in standins
396
396
397 match.matchfn = matchfn
397 match.matchfn = matchfn
398 result = orig(text=text, user=user, date=date, match=match,
398 result = orig(text=text, user=user, date=date, match=match,
399 force=force, editor=editor, extra=extra)
399 force=force, editor=editor, extra=extra)
400 # This needs to be after commit; otherwise precommit hooks
400 # This needs to be after commit; otherwise precommit hooks
401 # get the wrong status
401 # get the wrong status
402 lfdirstate.write()
402 lfdirstate.write()
403 return result
403 return result
404 finally:
404 finally:
405 wlock.release()
405 wlock.release()
406
406
407 def push(self, remote, force=False, revs=None, newbranch=False):
407 def push(self, remote, force=False, revs=None, newbranch=False):
408 if remote.local():
408 if remote.local():
409 missing = set(self.requirements) - remote.local().supported
409 missing = set(self.requirements) - remote.local().supported
410 if missing:
410 if missing:
411 msg = _("required features are not"
411 msg = _("required features are not"
412 " supported in the destination:"
412 " supported in the destination:"
413 " %s") % (', '.join(sorted(missing)))
413 " %s") % (', '.join(sorted(missing)))
414 raise util.Abort(msg)
414 raise util.Abort(msg)
415 return super(lfilesrepo, self).push(remote, force=force, revs=revs,
415 return super(lfilesrepo, self).push(remote, force=force, revs=revs,
416 newbranch=newbranch)
416 newbranch=newbranch)
417
417
418 def _subdirlfs(self, files, lfiles):
418 def _subdirlfs(self, files, lfiles):
419 '''
419 '''
420 Adjust matched file list
420 Adjust matched file list
421 If we pass a directory to commit whose only commitable files
421 If we pass a directory to commit whose only commitable files
422 are largefiles, the core commit code aborts before finding
422 are largefiles, the core commit code aborts before finding
423 the largefiles.
423 the largefiles.
424 So we do the following:
424 So we do the following:
425 For directories that only have largefiles as matches,
425 For directories that only have largefiles as matches,
426 we explicitly add the largefiles to the match list and remove
426 we explicitly add the largefiles to the match list and remove
427 the directory.
427 the directory.
428 In other cases, we leave the match list unmodified.
428 In other cases, we leave the match list unmodified.
429 '''
429 '''
430 actualfiles = []
430 actualfiles = []
431 dirs = []
431 dirs = []
432 regulars = []
432 regulars = []
433
433
434 for f in files:
434 for f in files:
435 if lfutil.isstandin(f + '/'):
435 if lfutil.isstandin(f + '/'):
436 raise util.Abort(
436 raise util.Abort(
437 _('file "%s" is a largefile standin') % f,
437 _('file "%s" is a largefile standin') % f,
438 hint=('commit the largefile itself instead'))
438 hint=('commit the largefile itself instead'))
439 # Scan directories
439 # Scan directories
440 if os.path.isdir(self.wjoin(f)):
440 if os.path.isdir(self.wjoin(f)):
441 dirs.append(f)
441 dirs.append(f)
442 else:
442 else:
443 regulars.append(f)
443 regulars.append(f)
444
444
445 for f in dirs:
445 for f in dirs:
446 matcheddir = False
446 matcheddir = False
447 d = self.dirstate.normalize(f) + '/'
447 d = self.dirstate.normalize(f) + '/'
448 # Check for matched normal files
448 # Check for matched normal files
449 for mf in regulars:
449 for mf in regulars:
450 if self.dirstate.normalize(mf).startswith(d):
450 if self.dirstate.normalize(mf).startswith(d):
451 actualfiles.append(f)
451 actualfiles.append(f)
452 matcheddir = True
452 matcheddir = True
453 break
453 break
454 if not matcheddir:
454 if not matcheddir:
455 # If no normal match, manually append
455 # If no normal match, manually append
456 # any matching largefiles
456 # any matching largefiles
457 for lf in lfiles:
457 for lf in lfiles:
458 if self.dirstate.normalize(lf).startswith(d):
458 if self.dirstate.normalize(lf).startswith(d):
459 actualfiles.append(lf)
459 actualfiles.append(lf)
460 if not matcheddir:
460 if not matcheddir:
461 actualfiles.append(lfutil.standin(f))
461 actualfiles.append(lfutil.standin(f))
462 matcheddir = True
462 matcheddir = True
463 # Nothing in dir, so readd it
463 # Nothing in dir, so readd it
464 # and let commit reject it
464 # and let commit reject it
465 if not matcheddir:
465 if not matcheddir:
466 actualfiles.append(f)
466 actualfiles.append(f)
467
467
468 # Always add normal files
468 # Always add normal files
469 actualfiles += regulars
469 actualfiles += regulars
470 return actualfiles
470 return actualfiles
471
471
472 repo.__class__ = lfilesrepo
472 repo.__class__ = lfilesrepo
473
473
474 def prepushoutgoinghook(local, remote, outgoing):
474 def prepushoutgoinghook(local, remote, outgoing):
475 if outgoing.missing:
475 if outgoing.missing:
476 toupload = set()
476 toupload = set()
477 addfunc = lambda fn, lfhash: toupload.add(lfhash)
477 addfunc = lambda fn, lfhash: toupload.add(lfhash)
478 lfutil.getlfilestoupload(local, outgoing.missing, addfunc)
478 lfutil.getlfilestoupload(local, outgoing.missing, addfunc)
479 lfcommands.uploadlfiles(ui, local, remote, toupload)
479 lfcommands.uploadlfiles(ui, local, remote, toupload)
480 repo.prepushoutgoinghooks.add("largefiles", prepushoutgoinghook)
480 repo.prepushoutgoinghooks.add("largefiles", prepushoutgoinghook)
481
481
482 def checkrequireslfiles(ui, repo, **kwargs):
482 def checkrequireslfiles(ui, repo, **kwargs):
483 if 'largefiles' not in repo.requirements and util.any(
483 if 'largefiles' not in repo.requirements and util.any(
484 lfutil.shortname+'/' in f[0] for f in repo.store.datafiles()):
484 lfutil.shortname+'/' in f[0] for f in repo.store.datafiles()):
485 repo.requirements.add('largefiles')
485 repo.requirements.add('largefiles')
486 repo._writerequirements()
486 repo._writerequirements()
487
487
488 ui.setconfig('hooks', 'changegroup.lfiles', checkrequireslfiles,
488 ui.setconfig('hooks', 'changegroup.lfiles', checkrequireslfiles,
489 'largefiles')
489 'largefiles')
490 ui.setconfig('hooks', 'commit.lfiles', checkrequireslfiles, 'largefiles')
490 ui.setconfig('hooks', 'commit.lfiles', checkrequireslfiles, 'largefiles')
General Comments 0
You need to be logged in to leave comments. Login now