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