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