##// END OF EJS Templates
largefiles: ignore removal status of files not managed in the target context...
FUJIWARA Katsunori -
r23089:197dc458 stable
parent child Browse files
Show More
@@ -1,470 +1,477 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, scmutil
15 from mercurial import localrepo, scmutil
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 orig = super(lfilesrepo, self).status
82 if not self.lfstatus:
82 if not self.lfstatus:
83 return orig(node1, node2, match, listignored, listclean,
83 return orig(node1, node2, match, listignored, listclean,
84 listunknown, listsubrepos)
84 listunknown, listsubrepos)
85
85
86 # 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
87 self.lfstatus = False
87 self.lfstatus = False
88 ctx1 = self[node1]
88 ctx1 = self[node1]
89 ctx2 = self[node2]
89 ctx2 = self[node2]
90 working = ctx2.rev() is None
90 working = ctx2.rev() is None
91 parentworking = working and ctx1 == self['.']
91 parentworking = working and ctx1 == self['.']
92
92
93 if match is None:
93 if match is None:
94 match = match_.always(self.root, self.getcwd())
94 match = match_.always(self.root, self.getcwd())
95
95
96 wlock = None
96 wlock = None
97 try:
97 try:
98 try:
98 try:
99 # updating the dirstate is optional
99 # updating the dirstate is optional
100 # so we don't wait on the lock
100 # so we don't wait on the lock
101 wlock = self.wlock(False)
101 wlock = self.wlock(False)
102 except error.LockError:
102 except error.LockError:
103 pass
103 pass
104
104
105 # First check if there were files specified on the
105 # First check if there were files specified on the
106 # command line. If there were, and none of them were
106 # command line. If there were, and none of them were
107 # largefiles, we should just bail here and let super
107 # largefiles, we should just bail here and let super
108 # handle it -- thus gaining a big performance boost.
108 # handle it -- thus gaining a big performance boost.
109 lfdirstate = lfutil.openlfdirstate(ui, self)
109 lfdirstate = lfutil.openlfdirstate(ui, self)
110 if match.files() and not match.anypats():
110 if match.files() and not match.anypats():
111 for f in lfdirstate:
111 for f in lfdirstate:
112 if match(f):
112 if match(f):
113 break
113 break
114 else:
114 else:
115 return orig(node1, node2, match, listignored, listclean,
115 return orig(node1, node2, match, listignored, listclean,
116 listunknown, listsubrepos)
116 listunknown, listsubrepos)
117
117
118 # Create a copy of match that matches standins instead
118 # Create a copy of match that matches standins instead
119 # of largefiles.
119 # of largefiles.
120 def tostandins(files):
120 def tostandins(files):
121 if not working:
121 if not working:
122 return files
122 return files
123 newfiles = []
123 newfiles = []
124 dirstate = self.dirstate
124 dirstate = self.dirstate
125 for f in files:
125 for f in files:
126 sf = lfutil.standin(f)
126 sf = lfutil.standin(f)
127 if sf in dirstate:
127 if sf in dirstate:
128 newfiles.append(sf)
128 newfiles.append(sf)
129 elif sf in dirstate.dirs():
129 elif sf in dirstate.dirs():
130 # Directory entries could be regular or
130 # Directory entries could be regular or
131 # standin, check both
131 # standin, check both
132 newfiles.extend((f, sf))
132 newfiles.extend((f, sf))
133 else:
133 else:
134 newfiles.append(f)
134 newfiles.append(f)
135 return newfiles
135 return newfiles
136
136
137 m = copy.copy(match)
137 m = copy.copy(match)
138 m._files = tostandins(m._files)
138 m._files = tostandins(m._files)
139
139
140 result = orig(node1, node2, m, ignored, clean, unknown,
140 result = orig(node1, node2, m, ignored, clean, unknown,
141 listsubrepos)
141 listsubrepos)
142 if working:
142 if working:
143
143
144 def sfindirstate(f):
144 def sfindirstate(f):
145 sf = lfutil.standin(f)
145 sf = lfutil.standin(f)
146 dirstate = self.dirstate
146 dirstate = self.dirstate
147 return sf in dirstate or sf in dirstate.dirs()
147 return sf in dirstate or sf in dirstate.dirs()
148
148
149 match._files = [f for f in match._files
149 match._files = [f for f in match._files
150 if sfindirstate(f)]
150 if sfindirstate(f)]
151 # Don't waste time getting the ignored and unknown
151 # Don't waste time getting the ignored and unknown
152 # files from lfdirstate
152 # files from lfdirstate
153 unsure, s = lfdirstate.status(match, [], False, listclean,
153 unsure, s = lfdirstate.status(match, [], False, listclean,
154 False)
154 False)
155 (modified, added, removed, clean) = (s.modified, s.added,
155 (modified, added, removed, clean) = (s.modified, s.added,
156 s.removed, s.clean)
156 s.removed, s.clean)
157 if parentworking:
157 if parentworking:
158 for lfile in unsure:
158 for lfile in unsure:
159 standin = lfutil.standin(lfile)
159 standin = lfutil.standin(lfile)
160 if standin not in ctx1:
160 if standin not in ctx1:
161 # from second parent
161 # from second parent
162 modified.append(lfile)
162 modified.append(lfile)
163 elif ctx1[standin].data().strip() \
163 elif ctx1[standin].data().strip() \
164 != lfutil.hashfile(self.wjoin(lfile)):
164 != lfutil.hashfile(self.wjoin(lfile)):
165 modified.append(lfile)
165 modified.append(lfile)
166 else:
166 else:
167 if listclean:
167 if listclean:
168 clean.append(lfile)
168 clean.append(lfile)
169 lfdirstate.normal(lfile)
169 lfdirstate.normal(lfile)
170 else:
170 else:
171 tocheck = unsure + modified + added + clean
171 tocheck = unsure + modified + added + clean
172 modified, added, clean = [], [], []
172 modified, added, clean = [], [], []
173
173
174 for lfile in tocheck:
174 for lfile in tocheck:
175 standin = lfutil.standin(lfile)
175 standin = lfutil.standin(lfile)
176 if standin in ctx1:
176 if standin in ctx1:
177 if ctx1[standin].data().strip() != \
177 if ctx1[standin].data().strip() != \
178 lfutil.hashfile(self.wjoin(lfile)):
178 lfutil.hashfile(self.wjoin(lfile)):
179 modified.append(lfile)
179 modified.append(lfile)
180 elif listclean:
180 elif listclean:
181 clean.append(lfile)
181 clean.append(lfile)
182 else:
182 else:
183 added.append(lfile)
183 added.append(lfile)
184
184
185 # at this point, 'removed' contains largefiles
186 # marked as 'R' in the working context.
187 # then, largefiles not managed also in the target
188 # context should be excluded from 'removed'.
189 removed = [lfile for lfile in removed
190 if lfutil.standin(lfile) in ctx1]
191
185 # Standins no longer found in lfdirstate has been
192 # Standins no longer found in lfdirstate has been
186 # removed
193 # removed
187 for standin in ctx1.walk(lfutil.getstandinmatcher(self)):
194 for standin in ctx1.walk(lfutil.getstandinmatcher(self)):
188 lfile = lfutil.splitstandin(standin)
195 lfile = lfutil.splitstandin(standin)
189 if not match(lfile):
196 if not match(lfile):
190 continue
197 continue
191 if lfile not in lfdirstate:
198 if lfile not in lfdirstate:
192 removed.append(lfile)
199 removed.append(lfile)
193
200
194 # Filter result lists
201 # Filter result lists
195 result = list(result)
202 result = list(result)
196
203
197 # Largefiles are not really removed when they're
204 # Largefiles are not really removed when they're
198 # still in the normal dirstate. Likewise, normal
205 # still in the normal dirstate. Likewise, normal
199 # files are not really removed if they are still in
206 # files are not really removed if they are still in
200 # lfdirstate. This happens in merges where files
207 # lfdirstate. This happens in merges where files
201 # change type.
208 # change type.
202 removed = [f for f in removed
209 removed = [f for f in removed
203 if f not in self.dirstate]
210 if f not in self.dirstate]
204 result[2] = [f for f in result[2]
211 result[2] = [f for f in result[2]
205 if f not in lfdirstate]
212 if f not in lfdirstate]
206
213
207 lfiles = set(lfdirstate._map)
214 lfiles = set(lfdirstate._map)
208 # Unknown files
215 # Unknown files
209 result[4] = set(result[4]).difference(lfiles)
216 result[4] = set(result[4]).difference(lfiles)
210 # Ignored files
217 # Ignored files
211 result[5] = set(result[5]).difference(lfiles)
218 result[5] = set(result[5]).difference(lfiles)
212 # combine normal files and largefiles
219 # combine normal files and largefiles
213 normals = [[fn for fn in filelist
220 normals = [[fn for fn in filelist
214 if not lfutil.isstandin(fn)]
221 if not lfutil.isstandin(fn)]
215 for filelist in result]
222 for filelist in result]
216 lfstatus = (modified, added, removed, s.deleted, [], [],
223 lfstatus = (modified, added, removed, s.deleted, [], [],
217 clean)
224 clean)
218 result = [sorted(list1 + list2)
225 result = [sorted(list1 + list2)
219 for (list1, list2) in zip(normals, lfstatus)]
226 for (list1, list2) in zip(normals, lfstatus)]
220 else: # not against working directory
227 else: # not against working directory
221 result = [[lfutil.splitstandin(f) or f for f in items]
228 result = [[lfutil.splitstandin(f) or f for f in items]
222 for items in result]
229 for items in result]
223
230
224 if wlock:
231 if wlock:
225 lfdirstate.write()
232 lfdirstate.write()
226
233
227 finally:
234 finally:
228 if wlock:
235 if wlock:
229 wlock.release()
236 wlock.release()
230
237
231 self.lfstatus = True
238 self.lfstatus = True
232 return scmutil.status(*result)
239 return scmutil.status(*result)
233
240
234 # As part of committing, copy all of the largefiles into the
241 # As part of committing, copy all of the largefiles into the
235 # cache.
242 # cache.
236 def commitctx(self, *args, **kwargs):
243 def commitctx(self, *args, **kwargs):
237 node = super(lfilesrepo, self).commitctx(*args, **kwargs)
244 node = super(lfilesrepo, self).commitctx(*args, **kwargs)
238 lfutil.copyalltostore(self, node)
245 lfutil.copyalltostore(self, node)
239 return node
246 return node
240
247
241 # Before commit, largefile standins have not had their
248 # Before commit, largefile standins have not had their
242 # contents updated to reflect the hash of their largefile.
249 # contents updated to reflect the hash of their largefile.
243 # Do that here.
250 # Do that here.
244 def commit(self, text="", user=None, date=None, match=None,
251 def commit(self, text="", user=None, date=None, match=None,
245 force=False, editor=False, extra={}):
252 force=False, editor=False, extra={}):
246 orig = super(lfilesrepo, self).commit
253 orig = super(lfilesrepo, self).commit
247
254
248 wlock = self.wlock()
255 wlock = self.wlock()
249 try:
256 try:
250 # Case 0: Automated committing
257 # Case 0: Automated committing
251 #
258 #
252 # While automated committing (like rebase, transplant
259 # While automated committing (like rebase, transplant
253 # and so on), this code path is used to avoid:
260 # and so on), this code path is used to avoid:
254 # (1) updating standins, because standins should
261 # (1) updating standins, because standins should
255 # be already updated at this point
262 # be already updated at this point
256 # (2) aborting when stadnins are matched by "match",
263 # (2) aborting when stadnins are matched by "match",
257 # because automated committing may specify them directly
264 # because automated committing may specify them directly
258 #
265 #
259 if getattr(self, "_isrebasing", False) or \
266 if getattr(self, "_isrebasing", False) or \
260 getattr(self, "_istransplanting", False):
267 getattr(self, "_istransplanting", False):
261 result = orig(text=text, user=user, date=date, match=match,
268 result = orig(text=text, user=user, date=date, match=match,
262 force=force, editor=editor, extra=extra)
269 force=force, editor=editor, extra=extra)
263
270
264 if result:
271 if result:
265 lfdirstate = lfutil.openlfdirstate(ui, self)
272 lfdirstate = lfutil.openlfdirstate(ui, self)
266 for f in self[result].files():
273 for f in self[result].files():
267 if lfutil.isstandin(f):
274 if lfutil.isstandin(f):
268 lfile = lfutil.splitstandin(f)
275 lfile = lfutil.splitstandin(f)
269 lfutil.synclfdirstate(self, lfdirstate, lfile,
276 lfutil.synclfdirstate(self, lfdirstate, lfile,
270 False)
277 False)
271 lfdirstate.write()
278 lfdirstate.write()
272
279
273 return result
280 return result
274 # Case 1: user calls commit with no specific files or
281 # Case 1: user calls commit with no specific files or
275 # include/exclude patterns: refresh and commit all files that
282 # include/exclude patterns: refresh and commit all files that
276 # are "dirty".
283 # are "dirty".
277 if ((match is None) or
284 if ((match is None) or
278 (not match.anypats() and not match.files())):
285 (not match.anypats() and not match.files())):
279 # Spend a bit of time here to get a list of files we know
286 # Spend a bit of time here to get a list of files we know
280 # are modified so we can compare only against those.
287 # are modified so we can compare only against those.
281 # It can cost a lot of time (several seconds)
288 # It can cost a lot of time (several seconds)
282 # otherwise to update all standins if the largefiles are
289 # otherwise to update all standins if the largefiles are
283 # large.
290 # large.
284 lfdirstate = lfutil.openlfdirstate(ui, self)
291 lfdirstate = lfutil.openlfdirstate(ui, self)
285 dirtymatch = match_.always(self.root, self.getcwd())
292 dirtymatch = match_.always(self.root, self.getcwd())
286 unsure, s = lfdirstate.status(dirtymatch, [], False, False,
293 unsure, s = lfdirstate.status(dirtymatch, [], False, False,
287 False)
294 False)
288 modifiedfiles = unsure + s.modified + s.added + s.removed
295 modifiedfiles = unsure + s.modified + s.added + s.removed
289 lfiles = lfutil.listlfiles(self)
296 lfiles = lfutil.listlfiles(self)
290 # this only loops through largefiles that exist (not
297 # this only loops through largefiles that exist (not
291 # removed/renamed)
298 # removed/renamed)
292 for lfile in lfiles:
299 for lfile in lfiles:
293 if lfile in modifiedfiles:
300 if lfile in modifiedfiles:
294 if os.path.exists(
301 if os.path.exists(
295 self.wjoin(lfutil.standin(lfile))):
302 self.wjoin(lfutil.standin(lfile))):
296 # this handles the case where a rebase is being
303 # this handles the case where a rebase is being
297 # performed and the working copy is not updated
304 # performed and the working copy is not updated
298 # yet.
305 # yet.
299 if os.path.exists(self.wjoin(lfile)):
306 if os.path.exists(self.wjoin(lfile)):
300 lfutil.updatestandin(self,
307 lfutil.updatestandin(self,
301 lfutil.standin(lfile))
308 lfutil.standin(lfile))
302 lfdirstate.normal(lfile)
309 lfdirstate.normal(lfile)
303
310
304 result = orig(text=text, user=user, date=date, match=match,
311 result = orig(text=text, user=user, date=date, match=match,
305 force=force, editor=editor, extra=extra)
312 force=force, editor=editor, extra=extra)
306
313
307 if result is not None:
314 if result is not None:
308 for lfile in lfdirstate:
315 for lfile in lfdirstate:
309 if lfile in modifiedfiles:
316 if lfile in modifiedfiles:
310 if (not os.path.exists(self.wjoin(
317 if (not os.path.exists(self.wjoin(
311 lfutil.standin(lfile)))) or \
318 lfutil.standin(lfile)))) or \
312 (not os.path.exists(self.wjoin(lfile))):
319 (not os.path.exists(self.wjoin(lfile))):
313 lfdirstate.drop(lfile)
320 lfdirstate.drop(lfile)
314
321
315 # This needs to be after commit; otherwise precommit hooks
322 # This needs to be after commit; otherwise precommit hooks
316 # get the wrong status
323 # get the wrong status
317 lfdirstate.write()
324 lfdirstate.write()
318 return result
325 return result
319
326
320 lfiles = lfutil.listlfiles(self)
327 lfiles = lfutil.listlfiles(self)
321 match._files = self._subdirlfs(match.files(), lfiles)
328 match._files = self._subdirlfs(match.files(), lfiles)
322
329
323 # Case 2: user calls commit with specified patterns: refresh
330 # Case 2: user calls commit with specified patterns: refresh
324 # any matching big files.
331 # any matching big files.
325 smatcher = lfutil.composestandinmatcher(self, match)
332 smatcher = lfutil.composestandinmatcher(self, match)
326 standins = self.dirstate.walk(smatcher, [], False, False)
333 standins = self.dirstate.walk(smatcher, [], False, False)
327
334
328 # No matching big files: get out of the way and pass control to
335 # No matching big files: get out of the way and pass control to
329 # the usual commit() method.
336 # the usual commit() method.
330 if not standins:
337 if not standins:
331 return orig(text=text, user=user, date=date, match=match,
338 return orig(text=text, user=user, date=date, match=match,
332 force=force, editor=editor, extra=extra)
339 force=force, editor=editor, extra=extra)
333
340
334 # Refresh all matching big files. It's possible that the
341 # Refresh all matching big files. It's possible that the
335 # commit will end up failing, in which case the big files will
342 # commit will end up failing, in which case the big files will
336 # stay refreshed. No harm done: the user modified them and
343 # stay refreshed. No harm done: the user modified them and
337 # asked to commit them, so sooner or later we're going to
344 # asked to commit them, so sooner or later we're going to
338 # refresh the standins. Might as well leave them refreshed.
345 # refresh the standins. Might as well leave them refreshed.
339 lfdirstate = lfutil.openlfdirstate(ui, self)
346 lfdirstate = lfutil.openlfdirstate(ui, self)
340 for standin in standins:
347 for standin in standins:
341 lfile = lfutil.splitstandin(standin)
348 lfile = lfutil.splitstandin(standin)
342 if lfdirstate[lfile] != 'r':
349 if lfdirstate[lfile] != 'r':
343 lfutil.updatestandin(self, standin)
350 lfutil.updatestandin(self, standin)
344 lfdirstate.normal(lfile)
351 lfdirstate.normal(lfile)
345 else:
352 else:
346 lfdirstate.drop(lfile)
353 lfdirstate.drop(lfile)
347
354
348 # Cook up a new matcher that only matches regular files or
355 # Cook up a new matcher that only matches regular files or
349 # standins corresponding to the big files requested by the
356 # standins corresponding to the big files requested by the
350 # user. Have to modify _files to prevent commit() from
357 # user. Have to modify _files to prevent commit() from
351 # complaining "not tracked" for big files.
358 # complaining "not tracked" for big files.
352 match = copy.copy(match)
359 match = copy.copy(match)
353 origmatchfn = match.matchfn
360 origmatchfn = match.matchfn
354
361
355 # Check both the list of largefiles and the list of
362 # Check both the list of largefiles and the list of
356 # standins because if a largefile was removed, it
363 # standins because if a largefile was removed, it
357 # won't be in the list of largefiles at this point
364 # won't be in the list of largefiles at this point
358 match._files += sorted(standins)
365 match._files += sorted(standins)
359
366
360 actualfiles = []
367 actualfiles = []
361 for f in match._files:
368 for f in match._files:
362 fstandin = lfutil.standin(f)
369 fstandin = lfutil.standin(f)
363
370
364 # ignore known largefiles and standins
371 # ignore known largefiles and standins
365 if f in lfiles or fstandin in standins:
372 if f in lfiles or fstandin in standins:
366 continue
373 continue
367
374
368 actualfiles.append(f)
375 actualfiles.append(f)
369 match._files = actualfiles
376 match._files = actualfiles
370
377
371 def matchfn(f):
378 def matchfn(f):
372 if origmatchfn(f):
379 if origmatchfn(f):
373 return f not in lfiles
380 return f not in lfiles
374 else:
381 else:
375 return f in standins
382 return f in standins
376
383
377 match.matchfn = matchfn
384 match.matchfn = matchfn
378 result = orig(text=text, user=user, date=date, match=match,
385 result = orig(text=text, user=user, date=date, match=match,
379 force=force, editor=editor, extra=extra)
386 force=force, editor=editor, extra=extra)
380 # This needs to be after commit; otherwise precommit hooks
387 # This needs to be after commit; otherwise precommit hooks
381 # get the wrong status
388 # get the wrong status
382 lfdirstate.write()
389 lfdirstate.write()
383 return result
390 return result
384 finally:
391 finally:
385 wlock.release()
392 wlock.release()
386
393
387 def push(self, remote, force=False, revs=None, newbranch=False):
394 def push(self, remote, force=False, revs=None, newbranch=False):
388 if remote.local():
395 if remote.local():
389 missing = set(self.requirements) - remote.local().supported
396 missing = set(self.requirements) - remote.local().supported
390 if missing:
397 if missing:
391 msg = _("required features are not"
398 msg = _("required features are not"
392 " supported in the destination:"
399 " supported in the destination:"
393 " %s") % (', '.join(sorted(missing)))
400 " %s") % (', '.join(sorted(missing)))
394 raise util.Abort(msg)
401 raise util.Abort(msg)
395 return super(lfilesrepo, self).push(remote, force=force, revs=revs,
402 return super(lfilesrepo, self).push(remote, force=force, revs=revs,
396 newbranch=newbranch)
403 newbranch=newbranch)
397
404
398 def _subdirlfs(self, files, lfiles):
405 def _subdirlfs(self, files, lfiles):
399 '''
406 '''
400 Adjust matched file list
407 Adjust matched file list
401 If we pass a directory to commit whose only commitable files
408 If we pass a directory to commit whose only commitable files
402 are largefiles, the core commit code aborts before finding
409 are largefiles, the core commit code aborts before finding
403 the largefiles.
410 the largefiles.
404 So we do the following:
411 So we do the following:
405 For directories that only have largefiles as matches,
412 For directories that only have largefiles as matches,
406 we explicitly add the largefiles to the match list and remove
413 we explicitly add the largefiles to the match list and remove
407 the directory.
414 the directory.
408 In other cases, we leave the match list unmodified.
415 In other cases, we leave the match list unmodified.
409 '''
416 '''
410 actualfiles = []
417 actualfiles = []
411 dirs = []
418 dirs = []
412 regulars = []
419 regulars = []
413
420
414 for f in files:
421 for f in files:
415 if lfutil.isstandin(f + '/'):
422 if lfutil.isstandin(f + '/'):
416 raise util.Abort(
423 raise util.Abort(
417 _('file "%s" is a largefile standin') % f,
424 _('file "%s" is a largefile standin') % f,
418 hint=('commit the largefile itself instead'))
425 hint=('commit the largefile itself instead'))
419 # Scan directories
426 # Scan directories
420 if os.path.isdir(self.wjoin(f)):
427 if os.path.isdir(self.wjoin(f)):
421 dirs.append(f)
428 dirs.append(f)
422 else:
429 else:
423 regulars.append(f)
430 regulars.append(f)
424
431
425 for f in dirs:
432 for f in dirs:
426 matcheddir = False
433 matcheddir = False
427 d = self.dirstate.normalize(f) + '/'
434 d = self.dirstate.normalize(f) + '/'
428 # Check for matched normal files
435 # Check for matched normal files
429 for mf in regulars:
436 for mf in regulars:
430 if self.dirstate.normalize(mf).startswith(d):
437 if self.dirstate.normalize(mf).startswith(d):
431 actualfiles.append(f)
438 actualfiles.append(f)
432 matcheddir = True
439 matcheddir = True
433 break
440 break
434 if not matcheddir:
441 if not matcheddir:
435 # If no normal match, manually append
442 # If no normal match, manually append
436 # any matching largefiles
443 # any matching largefiles
437 for lf in lfiles:
444 for lf in lfiles:
438 if self.dirstate.normalize(lf).startswith(d):
445 if self.dirstate.normalize(lf).startswith(d):
439 actualfiles.append(lf)
446 actualfiles.append(lf)
440 if not matcheddir:
447 if not matcheddir:
441 actualfiles.append(lfutil.standin(f))
448 actualfiles.append(lfutil.standin(f))
442 matcheddir = True
449 matcheddir = True
443 # Nothing in dir, so readd it
450 # Nothing in dir, so readd it
444 # and let commit reject it
451 # and let commit reject it
445 if not matcheddir:
452 if not matcheddir:
446 actualfiles.append(f)
453 actualfiles.append(f)
447
454
448 # Always add normal files
455 # Always add normal files
449 actualfiles += regulars
456 actualfiles += regulars
450 return actualfiles
457 return actualfiles
451
458
452 repo.__class__ = lfilesrepo
459 repo.__class__ = lfilesrepo
453
460
454 def prepushoutgoinghook(local, remote, outgoing):
461 def prepushoutgoinghook(local, remote, outgoing):
455 if outgoing.missing:
462 if outgoing.missing:
456 toupload = set()
463 toupload = set()
457 addfunc = lambda fn, lfhash: toupload.add(lfhash)
464 addfunc = lambda fn, lfhash: toupload.add(lfhash)
458 lfutil.getlfilestoupload(local, outgoing.missing, addfunc)
465 lfutil.getlfilestoupload(local, outgoing.missing, addfunc)
459 lfcommands.uploadlfiles(ui, local, remote, toupload)
466 lfcommands.uploadlfiles(ui, local, remote, toupload)
460 repo.prepushoutgoinghooks.add("largefiles", prepushoutgoinghook)
467 repo.prepushoutgoinghooks.add("largefiles", prepushoutgoinghook)
461
468
462 def checkrequireslfiles(ui, repo, **kwargs):
469 def checkrequireslfiles(ui, repo, **kwargs):
463 if 'largefiles' not in repo.requirements and util.any(
470 if 'largefiles' not in repo.requirements and util.any(
464 lfutil.shortname+'/' in f[0] for f in repo.store.datafiles()):
471 lfutil.shortname+'/' in f[0] for f in repo.store.datafiles()):
465 repo.requirements.add('largefiles')
472 repo.requirements.add('largefiles')
466 repo._writerequirements()
473 repo._writerequirements()
467
474
468 ui.setconfig('hooks', 'changegroup.lfiles', checkrequireslfiles,
475 ui.setconfig('hooks', 'changegroup.lfiles', checkrequireslfiles,
469 'largefiles')
476 'largefiles')
470 ui.setconfig('hooks', 'commit.lfiles', checkrequireslfiles, 'largefiles')
477 ui.setconfig('hooks', 'commit.lfiles', checkrequireslfiles, 'largefiles')
@@ -1,546 +1,555 b''
1 This file focuses mainly on updating largefiles in the working
1 This file focuses mainly on updating largefiles in the working
2 directory (and ".hg/largefiles/dirstate")
2 directory (and ".hg/largefiles/dirstate")
3
3
4 $ cat >> $HGRCPATH <<EOF
4 $ cat >> $HGRCPATH <<EOF
5 > [ui]
5 > [ui]
6 > merge = internal:fail
6 > merge = internal:fail
7 > [extensions]
7 > [extensions]
8 > largefiles =
8 > largefiles =
9 > EOF
9 > EOF
10
10
11 $ hg init repo
11 $ hg init repo
12 $ cd repo
12 $ cd repo
13
13
14 $ echo large1 > large1
14 $ echo large1 > large1
15 $ echo large2 > large2
15 $ echo large2 > large2
16 $ hg add --large large1 large2
16 $ hg add --large large1 large2
17 $ echo normal1 > normal1
17 $ echo normal1 > normal1
18 $ hg add normal1
18 $ hg add normal1
19 $ hg commit -m '#0'
19 $ hg commit -m '#0'
20 $ echo 'large1 in #1' > large1
20 $ echo 'large1 in #1' > large1
21 $ echo 'normal1 in #1' > normal1
21 $ echo 'normal1 in #1' > normal1
22 $ hg commit -m '#1'
22 $ hg commit -m '#1'
23 $ hg update -q -C 0
23 $ hg update -q -C 0
24 $ echo 'large2 in #2' > large2
24 $ echo 'large2 in #2' > large2
25 $ hg commit -m '#2'
25 $ hg commit -m '#2'
26 created new head
26 created new head
27
27
28 Test that "hg merge" updates largefiles from "other" correctly
28 Test that "hg merge" updates largefiles from "other" correctly
29
29
30 (getting largefiles from "other" normally)
30 (getting largefiles from "other" normally)
31
31
32 $ hg status -A large1
32 $ hg status -A large1
33 C large1
33 C large1
34 $ cat large1
34 $ cat large1
35 large1
35 large1
36 $ cat .hglf/large1
36 $ cat .hglf/large1
37 4669e532d5b2c093a78eca010077e708a071bb64
37 4669e532d5b2c093a78eca010077e708a071bb64
38 $ hg merge --config debug.dirstate.delaywrite=2
38 $ hg merge --config debug.dirstate.delaywrite=2
39 getting changed largefiles
39 getting changed largefiles
40 1 largefiles updated, 0 removed
40 1 largefiles updated, 0 removed
41 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
41 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
42 (branch merge, don't forget to commit)
42 (branch merge, don't forget to commit)
43 $ hg status -A large1
43 $ hg status -A large1
44 M large1
44 M large1
45 $ cat large1
45 $ cat large1
46 large1 in #1
46 large1 in #1
47 $ cat .hglf/large1
47 $ cat .hglf/large1
48 58e24f733a964da346e2407a2bee99d9001184f5
48 58e24f733a964da346e2407a2bee99d9001184f5
49 $ hg diff -c 1 --nodates .hglf/large1 | grep '^[+-][0-9a-z]'
49 $ hg diff -c 1 --nodates .hglf/large1 | grep '^[+-][0-9a-z]'
50 -4669e532d5b2c093a78eca010077e708a071bb64
50 -4669e532d5b2c093a78eca010077e708a071bb64
51 +58e24f733a964da346e2407a2bee99d9001184f5
51 +58e24f733a964da346e2407a2bee99d9001184f5
52
52
53 (getting largefiles from "other" via conflict prompt)
53 (getting largefiles from "other" via conflict prompt)
54
54
55 $ hg update -q -C 2
55 $ hg update -q -C 2
56 $ echo 'large1 in #3' > large1
56 $ echo 'large1 in #3' > large1
57 $ echo 'normal1 in #3' > normal1
57 $ echo 'normal1 in #3' > normal1
58 $ hg commit -m '#3'
58 $ hg commit -m '#3'
59 $ cat .hglf/large1
59 $ cat .hglf/large1
60 e5bb990443d6a92aaf7223813720f7566c9dd05b
60 e5bb990443d6a92aaf7223813720f7566c9dd05b
61 $ hg merge --config debug.dirstate.delaywrite=2 --config ui.interactive=True <<EOF
61 $ hg merge --config debug.dirstate.delaywrite=2 --config ui.interactive=True <<EOF
62 > o
62 > o
63 > EOF
63 > EOF
64 largefile large1 has a merge conflict
64 largefile large1 has a merge conflict
65 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
65 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
66 keep (l)ocal e5bb990443d6a92aaf7223813720f7566c9dd05b or
66 keep (l)ocal e5bb990443d6a92aaf7223813720f7566c9dd05b or
67 take (o)ther 58e24f733a964da346e2407a2bee99d9001184f5? o
67 take (o)ther 58e24f733a964da346e2407a2bee99d9001184f5? o
68 merging normal1
68 merging normal1
69 warning: conflicts during merge.
69 warning: conflicts during merge.
70 merging normal1 incomplete! (edit conflicts, then use 'hg resolve --mark')
70 merging normal1 incomplete! (edit conflicts, then use 'hg resolve --mark')
71 getting changed largefiles
71 getting changed largefiles
72 1 largefiles updated, 0 removed
72 1 largefiles updated, 0 removed
73 0 files updated, 1 files merged, 0 files removed, 1 files unresolved
73 0 files updated, 1 files merged, 0 files removed, 1 files unresolved
74 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
74 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
75 [1]
75 [1]
76 $ hg status -A large1
76 $ hg status -A large1
77 M large1
77 M large1
78 $ cat large1
78 $ cat large1
79 large1 in #1
79 large1 in #1
80 $ cat .hglf/large1
80 $ cat .hglf/large1
81 58e24f733a964da346e2407a2bee99d9001184f5
81 58e24f733a964da346e2407a2bee99d9001184f5
82
82
83 Test that "hg revert -r REV" updates largefiles from "REV" correctly
83 Test that "hg revert -r REV" updates largefiles from "REV" correctly
84
84
85 $ hg update -q -C 3
85 $ hg update -q -C 3
86 $ hg status -A large1
86 $ hg status -A large1
87 C large1
87 C large1
88 $ cat large1
88 $ cat large1
89 large1 in #3
89 large1 in #3
90 $ cat .hglf/large1
90 $ cat .hglf/large1
91 e5bb990443d6a92aaf7223813720f7566c9dd05b
91 e5bb990443d6a92aaf7223813720f7566c9dd05b
92 $ hg diff -c 1 --nodates .hglf/large1 | grep '^[+-][0-9a-z]'
92 $ hg diff -c 1 --nodates .hglf/large1 | grep '^[+-][0-9a-z]'
93 -4669e532d5b2c093a78eca010077e708a071bb64
93 -4669e532d5b2c093a78eca010077e708a071bb64
94 +58e24f733a964da346e2407a2bee99d9001184f5
94 +58e24f733a964da346e2407a2bee99d9001184f5
95 $ hg revert --no-backup -r 1 --config debug.dirstate.delaywrite=2 large1
95 $ hg revert --no-backup -r 1 --config debug.dirstate.delaywrite=2 large1
96 $ hg status -A large1
96 $ hg status -A large1
97 M large1
97 M large1
98 $ cat large1
98 $ cat large1
99 large1 in #1
99 large1 in #1
100 $ cat .hglf/large1
100 $ cat .hglf/large1
101 58e24f733a964da346e2407a2bee99d9001184f5
101 58e24f733a964da346e2407a2bee99d9001184f5
102
102
103 Test that "hg rollback" restores status of largefiles correctly
103 Test that "hg rollback" restores status of largefiles correctly
104
104
105 $ hg update -C -q
105 $ hg update -C -q
106 $ hg remove large1
106 $ hg remove large1
107 $ test -f .hglf/large1
107 $ test -f .hglf/large1
108 [1]
108 [1]
109 $ hg forget large2
109 $ hg forget large2
110 $ test -f .hglf/large2
110 $ test -f .hglf/large2
111 [1]
111 [1]
112 $ echo largeX > largeX
112 $ echo largeX > largeX
113 $ hg add --large largeX
113 $ hg add --large largeX
114 $ cat .hglf/largeX
114 $ cat .hglf/largeX
115
115
116 $ hg commit -m 'will be rollback-ed soon'
116 $ hg commit -m 'will be rollback-ed soon'
117 $ echo largeY > largeY
117 $ echo largeY > largeY
118 $ hg add --large largeY
118 $ hg add --large largeY
119 #if windows
119 #if windows
120 $ hg status -A large1
120 $ hg status -A large1
121 large1: * (glob)
121 large1: * (glob)
122 #else
122 #else
123 $ hg status -A large1
123 $ hg status -A large1
124 large1: No such file or directory
124 large1: No such file or directory
125 #endif
125 #endif
126 $ hg status -A large2
126 $ hg status -A large2
127 ? large2
127 ? large2
128 $ hg status -A largeX
128 $ hg status -A largeX
129 C largeX
129 C largeX
130 $ hg status -A largeY
130 $ hg status -A largeY
131 A largeY
131 A largeY
132 $ hg rollback
132 $ hg rollback
133 repository tip rolled back to revision 3 (undo commit)
133 repository tip rolled back to revision 3 (undo commit)
134 working directory now based on revision 3
134 working directory now based on revision 3
135 $ hg status -A large1
135 $ hg status -A large1
136 R large1
136 R large1
137 $ test -f .hglf/large1
137 $ test -f .hglf/large1
138 [1]
138 [1]
139 $ hg status -A large2
139 $ hg status -A large2
140 R large2
140 R large2
141 $ test -f .hglf/large2
141 $ test -f .hglf/large2
142 [1]
142 [1]
143 $ hg status -A largeX
143 $ hg status -A largeX
144 A largeX
144 A largeX
145 $ cat .hglf/largeX
145 $ cat .hglf/largeX
146
146
147 $ hg status -A largeY
147 $ hg status -A largeY
148 ? largeY
148 ? largeY
149 $ test -f .hglf/largeY
149 $ test -f .hglf/largeY
150 [1]
150 [1]
151
151
152 Test that "hg rollback" restores standins correctly
152 Test that "hg rollback" restores standins correctly
153
153
154 $ hg commit -m 'will be rollback-ed soon'
154 $ hg commit -m 'will be rollback-ed soon'
155 $ hg update -q -C 2
155 $ hg update -q -C 2
156 $ cat large1
156 $ cat large1
157 large1
157 large1
158 $ cat .hglf/large1
158 $ cat .hglf/large1
159 4669e532d5b2c093a78eca010077e708a071bb64
159 4669e532d5b2c093a78eca010077e708a071bb64
160 $ cat large2
160 $ cat large2
161 large2 in #2
161 large2 in #2
162 $ cat .hglf/large2
162 $ cat .hglf/large2
163 3cfce6277e7668985707b6887ce56f9f62f6ccd9
163 3cfce6277e7668985707b6887ce56f9f62f6ccd9
164
164
165 $ hg rollback -q -f
165 $ hg rollback -q -f
166 $ cat large1
166 $ cat large1
167 large1
167 large1
168 $ cat .hglf/large1
168 $ cat .hglf/large1
169 4669e532d5b2c093a78eca010077e708a071bb64
169 4669e532d5b2c093a78eca010077e708a071bb64
170 $ cat large2
170 $ cat large2
171 large2 in #2
171 large2 in #2
172 $ cat .hglf/large2
172 $ cat .hglf/large2
173 3cfce6277e7668985707b6887ce56f9f62f6ccd9
173 3cfce6277e7668985707b6887ce56f9f62f6ccd9
174
174
175 (rollback the parent of the working directory, when the parent of it
175 (rollback the parent of the working directory, when the parent of it
176 is not branch-tip)
176 is not branch-tip)
177
177
178 $ hg update -q -C 1
178 $ hg update -q -C 1
179 $ cat .hglf/large1
179 $ cat .hglf/large1
180 58e24f733a964da346e2407a2bee99d9001184f5
180 58e24f733a964da346e2407a2bee99d9001184f5
181 $ cat .hglf/large2
181 $ cat .hglf/large2
182 1deebade43c8c498a3c8daddac0244dc55d1331d
182 1deebade43c8c498a3c8daddac0244dc55d1331d
183
183
184 $ echo normalX > normalX
184 $ echo normalX > normalX
185 $ hg add normalX
185 $ hg add normalX
186 $ hg commit -m 'will be rollback-ed soon'
186 $ hg commit -m 'will be rollback-ed soon'
187 $ hg rollback -q
187 $ hg rollback -q
188
188
189 $ cat .hglf/large1
189 $ cat .hglf/large1
190 58e24f733a964da346e2407a2bee99d9001184f5
190 58e24f733a964da346e2407a2bee99d9001184f5
191 $ cat .hglf/large2
191 $ cat .hglf/large2
192 1deebade43c8c498a3c8daddac0244dc55d1331d
192 1deebade43c8c498a3c8daddac0244dc55d1331d
193
193
194 Test that "hg status" shows status of largefiles correctly just after
194 Test that "hg status" shows status of largefiles correctly just after
195 automated commit like rebase/transplant
195 automated commit like rebase/transplant
196
196
197 $ cat >> .hg/hgrc <<EOF
197 $ cat >> .hg/hgrc <<EOF
198 > [extensions]
198 > [extensions]
199 > rebase =
199 > rebase =
200 > strip =
200 > strip =
201 > transplant =
201 > transplant =
202 > EOF
202 > EOF
203 $ hg update -q -C 1
203 $ hg update -q -C 1
204 $ hg remove large1
204 $ hg remove large1
205 $ echo largeX > largeX
205 $ echo largeX > largeX
206 $ hg add --large largeX
206 $ hg add --large largeX
207 $ hg commit -m '#4'
207 $ hg commit -m '#4'
208
208
209 $ hg rebase -s 1 -d 2 --keep
209 $ hg rebase -s 1 -d 2 --keep
210 #if windows
210 #if windows
211 $ hg status -A large1
211 $ hg status -A large1
212 large1: * (glob)
212 large1: * (glob)
213 #else
213 #else
214 $ hg status -A large1
214 $ hg status -A large1
215 large1: No such file or directory
215 large1: No such file or directory
216 #endif
216 #endif
217 $ hg status -A largeX
217 $ hg status -A largeX
218 C largeX
218 C largeX
219 $ hg strip -q 5
219 $ hg strip -q 5
220
220
221 $ hg update -q -C 2
221 $ hg update -q -C 2
222 $ hg transplant -q 1 4
222 $ hg transplant -q 1 4
223 #if windows
223 #if windows
224 $ hg status -A large1
224 $ hg status -A large1
225 large1: * (glob)
225 large1: * (glob)
226 #else
226 #else
227 $ hg status -A large1
227 $ hg status -A large1
228 large1: No such file or directory
228 large1: No such file or directory
229 #endif
229 #endif
230 $ hg status -A largeX
230 $ hg status -A largeX
231 C largeX
231 C largeX
232 $ hg strip -q 5
232 $ hg strip -q 5
233
233
234 $ hg update -q -C 2
234 $ hg update -q -C 2
235 $ hg transplant -q --merge 1 --merge 4
235 $ hg transplant -q --merge 1 --merge 4
236 #if windows
236 #if windows
237 $ hg status -A large1
237 $ hg status -A large1
238 large1: * (glob)
238 large1: * (glob)
239 #else
239 #else
240 $ hg status -A large1
240 $ hg status -A large1
241 large1: No such file or directory
241 large1: No such file or directory
242 #endif
242 #endif
243 $ hg status -A largeX
243 $ hg status -A largeX
244 C largeX
244 C largeX
245 $ hg strip -q 5
245 $ hg strip -q 5
246
246
247 Test that linear merge can detect modification (and conflict) correctly
247 Test that linear merge can detect modification (and conflict) correctly
248
248
249 (linear merge without conflict)
249 (linear merge without conflict)
250
250
251 $ echo 'large2 for linear merge (no conflict)' > large2
251 $ echo 'large2 for linear merge (no conflict)' > large2
252 $ hg update 3 --config debug.dirstate.delaywrite=2
252 $ hg update 3 --config debug.dirstate.delaywrite=2
253 getting changed largefiles
253 getting changed largefiles
254 1 largefiles updated, 0 removed
254 1 largefiles updated, 0 removed
255 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
255 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
256 $ hg status -A large2
256 $ hg status -A large2
257 M large2
257 M large2
258 $ cat large2
258 $ cat large2
259 large2 for linear merge (no conflict)
259 large2 for linear merge (no conflict)
260 $ cat .hglf/large2
260 $ cat .hglf/large2
261 9c4bf8f1b33536d6e5f89447e10620cfe52ea710
261 9c4bf8f1b33536d6e5f89447e10620cfe52ea710
262
262
263 (linear merge with conflict, choosing "other")
263 (linear merge with conflict, choosing "other")
264
264
265 $ hg update -q -C 2
265 $ hg update -q -C 2
266 $ echo 'large1 for linear merge (conflict)' > large1
266 $ echo 'large1 for linear merge (conflict)' > large1
267 $ hg update 3 --config ui.interactive=True <<EOF
267 $ hg update 3 --config ui.interactive=True <<EOF
268 > o
268 > o
269 > EOF
269 > EOF
270 largefile large1 has a merge conflict
270 largefile large1 has a merge conflict
271 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
271 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
272 keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or
272 keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or
273 take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b? o
273 take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b? o
274 getting changed largefiles
274 getting changed largefiles
275 1 largefiles updated, 0 removed
275 1 largefiles updated, 0 removed
276 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
276 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
277 $ hg status -A large1
277 $ hg status -A large1
278 C large1
278 C large1
279 $ cat large1
279 $ cat large1
280 large1 in #3
280 large1 in #3
281 $ cat .hglf/large1
281 $ cat .hglf/large1
282 e5bb990443d6a92aaf7223813720f7566c9dd05b
282 e5bb990443d6a92aaf7223813720f7566c9dd05b
283
283
284 (linear merge with conflict, choosing "local")
284 (linear merge with conflict, choosing "local")
285
285
286 $ hg update -q -C 2
286 $ hg update -q -C 2
287 $ echo 'large1 for linear merge (conflict)' > large1
287 $ echo 'large1 for linear merge (conflict)' > large1
288 $ hg update 3 --config debug.dirstate.delaywrite=2
288 $ hg update 3 --config debug.dirstate.delaywrite=2
289 largefile large1 has a merge conflict
289 largefile large1 has a merge conflict
290 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
290 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
291 keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or
291 keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or
292 take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b? l
292 take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b? l
293 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
293 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
294 $ hg status -A large1
294 $ hg status -A large1
295 M large1
295 M large1
296 $ cat large1
296 $ cat large1
297 large1 for linear merge (conflict)
297 large1 for linear merge (conflict)
298 $ cat .hglf/large1
298 $ cat .hglf/large1
299 ba94c2efe5b7c5e0af8d189295ce00553b0612b7
299 ba94c2efe5b7c5e0af8d189295ce00553b0612b7
300
300
301 Test a linear merge to a revision containing same-name normal file
301 Test a linear merge to a revision containing same-name normal file
302
302
303 $ hg update -q -C 3
303 $ hg update -q -C 3
304 $ hg remove large2
304 $ hg remove large2
305 $ echo 'large2 as normal file' > large2
305 $ echo 'large2 as normal file' > large2
306 $ hg add large2
306 $ hg add large2
307 $ echo 'large3 as normal file' > large3
307 $ echo 'large3 as normal file' > large3
308 $ hg add large3
308 $ hg add large3
309 $ hg commit -m '#5'
309 $ hg commit -m '#5'
310 $ hg manifest
310 $ hg manifest
311 .hglf/large1
311 .hglf/large1
312 large2
312 large2
313 large3
313 large3
314 normal1
314 normal1
315
315
316 (modified largefile is already switched to normal)
316 (modified largefile is already switched to normal)
317
317
318 $ hg update -q -C 2
318 $ hg update -q -C 2
319 $ echo 'modified large2 for linear merge' > large2
319 $ echo 'modified large2 for linear merge' > large2
320 $ hg update -q 5
320 $ hg update -q 5
321 local changed .hglf/large2 which remote deleted
321 local changed .hglf/large2 which remote deleted
322 use (c)hanged version or (d)elete? c
322 use (c)hanged version or (d)elete? c
323 remote turned local largefile large2 into a normal file
323 remote turned local largefile large2 into a normal file
324 keep (l)argefile or use (n)ormal file? l
324 keep (l)argefile or use (n)ormal file? l
325 $ hg debugdirstate --nodates | grep large2
325 $ hg debugdirstate --nodates | grep large2
326 a 0 -1 .hglf/large2
326 a 0 -1 .hglf/large2
327 r 0 0 large2
327 r 0 0 large2
328 $ hg status -A large2
328 $ hg status -A large2
329 A large2
329 A large2
330 $ cat large2
330 $ cat large2
331 modified large2 for linear merge
331 modified large2 for linear merge
332
332
333 (added largefile is already committed as normal)
333 (added largefile is already committed as normal)
334
334
335 $ hg update -q -C 2
335 $ hg update -q -C 2
336 $ echo 'large3 as large file for linear merge' > large3
336 $ echo 'large3 as large file for linear merge' > large3
337 $ hg add --large large3
337 $ hg add --large large3
338 $ hg update -q 5
338 $ hg update -q 5
339 remote turned local largefile large3 into a normal file
339 remote turned local largefile large3 into a normal file
340 keep (l)argefile or use (n)ormal file? l
340 keep (l)argefile or use (n)ormal file? l
341 $ hg debugdirstate --nodates | grep large3
341 $ hg debugdirstate --nodates | grep large3
342 a 0 -1 .hglf/large3
342 a 0 -1 .hglf/large3
343 r 0 0 large3
343 r 0 0 large3
344 $ hg status -A large3
344 $ hg status -A large3
345 A large3
345 A large3
346 $ cat large3
346 $ cat large3
347 large3 as large file for linear merge
347 large3 as large file for linear merge
348 $ rm -f large3 .hglf/large3
348 $ rm -f large3 .hglf/large3
349
349
350 Test that the internal linear merging works correctly
350 Test that the internal linear merging works correctly
351 (both heads are stripped to keep pairing of revision number and commit log)
351 (both heads are stripped to keep pairing of revision number and commit log)
352
352
353 $ hg update -q -C 2
353 $ hg update -q -C 2
354 $ hg strip 3 4
354 $ hg strip 3 4
355 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/9530e27857f7-backup.hg (glob)
355 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/9530e27857f7-backup.hg (glob)
356 $ mv .hg/strip-backup/9530e27857f7-backup.hg $TESTTMP
356 $ mv .hg/strip-backup/9530e27857f7-backup.hg $TESTTMP
357
357
358 (internal linear merging at "hg pull --update")
358 (internal linear merging at "hg pull --update")
359
359
360 $ echo 'large1 for linear merge (conflict)' > large1
360 $ echo 'large1 for linear merge (conflict)' > large1
361 $ echo 'large2 for linear merge (conflict with normal file)' > large2
361 $ echo 'large2 for linear merge (conflict with normal file)' > large2
362 $ hg pull --update --config debug.dirstate.delaywrite=2 $TESTTMP/9530e27857f7-backup.hg
362 $ hg pull --update --config debug.dirstate.delaywrite=2 $TESTTMP/9530e27857f7-backup.hg
363 pulling from $TESTTMP/9530e27857f7-backup.hg (glob)
363 pulling from $TESTTMP/9530e27857f7-backup.hg (glob)
364 searching for changes
364 searching for changes
365 adding changesets
365 adding changesets
366 adding manifests
366 adding manifests
367 adding file changes
367 adding file changes
368 added 3 changesets with 5 changes to 5 files
368 added 3 changesets with 5 changes to 5 files
369 local changed .hglf/large2 which remote deleted
369 local changed .hglf/large2 which remote deleted
370 use (c)hanged version or (d)elete? c
370 use (c)hanged version or (d)elete? c
371 remote turned local largefile large2 into a normal file
371 remote turned local largefile large2 into a normal file
372 keep (l)argefile or use (n)ormal file? l
372 keep (l)argefile or use (n)ormal file? l
373 largefile large1 has a merge conflict
373 largefile large1 has a merge conflict
374 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
374 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
375 keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or
375 keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or
376 take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b? l
376 take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b? l
377 2 files updated, 1 files merged, 0 files removed, 0 files unresolved
377 2 files updated, 1 files merged, 0 files removed, 0 files unresolved
378
378
379 $ hg status -A large1
379 $ hg status -A large1
380 M large1
380 M large1
381 $ cat large1
381 $ cat large1
382 large1 for linear merge (conflict)
382 large1 for linear merge (conflict)
383 $ cat .hglf/large1
383 $ cat .hglf/large1
384 ba94c2efe5b7c5e0af8d189295ce00553b0612b7
384 ba94c2efe5b7c5e0af8d189295ce00553b0612b7
385 $ hg status -A large2
385 $ hg status -A large2
386 A large2
386 A large2
387 $ cat large2
387 $ cat large2
388 large2 for linear merge (conflict with normal file)
388 large2 for linear merge (conflict with normal file)
389 $ cat .hglf/large2
389 $ cat .hglf/large2
390 d7591fe9be0f6227d90bddf3e4f52ff41fc1f544
390 d7591fe9be0f6227d90bddf3e4f52ff41fc1f544
391
391
392 (internal linear merging at "hg unbundle --update")
392 (internal linear merging at "hg unbundle --update")
393
393
394 $ hg update -q -C 2
394 $ hg update -q -C 2
395 $ hg rollback -q
395 $ hg rollback -q
396
396
397 $ echo 'large1 for linear merge (conflict)' > large1
397 $ echo 'large1 for linear merge (conflict)' > large1
398 $ echo 'large2 for linear merge (conflict with normal file)' > large2
398 $ echo 'large2 for linear merge (conflict with normal file)' > large2
399 $ hg unbundle --update --config debug.dirstate.delaywrite=2 $TESTTMP/9530e27857f7-backup.hg
399 $ hg unbundle --update --config debug.dirstate.delaywrite=2 $TESTTMP/9530e27857f7-backup.hg
400 adding changesets
400 adding changesets
401 adding manifests
401 adding manifests
402 adding file changes
402 adding file changes
403 added 3 changesets with 5 changes to 5 files
403 added 3 changesets with 5 changes to 5 files
404 local changed .hglf/large2 which remote deleted
404 local changed .hglf/large2 which remote deleted
405 use (c)hanged version or (d)elete? c
405 use (c)hanged version or (d)elete? c
406 remote turned local largefile large2 into a normal file
406 remote turned local largefile large2 into a normal file
407 keep (l)argefile or use (n)ormal file? l
407 keep (l)argefile or use (n)ormal file? l
408 largefile large1 has a merge conflict
408 largefile large1 has a merge conflict
409 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
409 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
410 keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or
410 keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or
411 take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b? l
411 take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b? l
412 2 files updated, 1 files merged, 0 files removed, 0 files unresolved
412 2 files updated, 1 files merged, 0 files removed, 0 files unresolved
413
413
414 $ hg status -A large1
414 $ hg status -A large1
415 M large1
415 M large1
416 $ cat large1
416 $ cat large1
417 large1 for linear merge (conflict)
417 large1 for linear merge (conflict)
418 $ cat .hglf/large1
418 $ cat .hglf/large1
419 ba94c2efe5b7c5e0af8d189295ce00553b0612b7
419 ba94c2efe5b7c5e0af8d189295ce00553b0612b7
420 $ hg status -A large2
420 $ hg status -A large2
421 A large2
421 A large2
422 $ cat large2
422 $ cat large2
423 large2 for linear merge (conflict with normal file)
423 large2 for linear merge (conflict with normal file)
424 $ cat .hglf/large2
424 $ cat .hglf/large2
425 d7591fe9be0f6227d90bddf3e4f52ff41fc1f544
425 d7591fe9be0f6227d90bddf3e4f52ff41fc1f544
426
426
427 (internal linear merging in subrepo at "hg update")
427 (internal linear merging in subrepo at "hg update")
428
428
429 $ cd ..
429 $ cd ..
430 $ hg init subparent
430 $ hg init subparent
431 $ cd subparent
431 $ cd subparent
432
432
433 $ hg clone -q -u 2 ../repo sub
433 $ hg clone -q -u 2 ../repo sub
434 $ cat > .hgsub <<EOF
434 $ cat > .hgsub <<EOF
435 > sub = sub
435 > sub = sub
436 > EOF
436 > EOF
437 $ hg add .hgsub
437 $ hg add .hgsub
438 $ hg commit -m '#0@parent'
438 $ hg commit -m '#0@parent'
439 $ cat .hgsubstate
439 $ cat .hgsubstate
440 f74e50bd9e5594b7cf1e6c5cbab86ddd25f3ca2f sub
440 f74e50bd9e5594b7cf1e6c5cbab86ddd25f3ca2f sub
441 $ hg -R sub update -q
441 $ hg -R sub update -q
442 $ hg commit -m '#1@parent'
442 $ hg commit -m '#1@parent'
443 $ cat .hgsubstate
443 $ cat .hgsubstate
444 d65e59e952a9638e2ce863b41a420ca723dd3e8d sub
444 d65e59e952a9638e2ce863b41a420ca723dd3e8d sub
445 $ hg update -q 0
445 $ hg update -q 0
446
446
447 $ echo 'large1 for linear merge (conflict)' > sub/large1
447 $ echo 'large1 for linear merge (conflict)' > sub/large1
448 $ echo 'large2 for linear merge (conflict with normal file)' > sub/large2
448 $ echo 'large2 for linear merge (conflict with normal file)' > sub/large2
449 $ hg update --config ui.interactive=True --config debug.dirstate.delaywrite=2 <<EOF
449 $ hg update --config ui.interactive=True --config debug.dirstate.delaywrite=2 <<EOF
450 > m
450 > m
451 > r
451 > r
452 > c
452 > c
453 > l
453 > l
454 > l
454 > l
455 > EOF
455 > EOF
456 subrepository sub diverged (local revision: f74e50bd9e55, remote revision: d65e59e952a9)
456 subrepository sub diverged (local revision: f74e50bd9e55, remote revision: d65e59e952a9)
457 (M)erge, keep (l)ocal or keep (r)emote? m
457 (M)erge, keep (l)ocal or keep (r)emote? m
458 subrepository sources for sub differ (in checked out version)
458 subrepository sources for sub differ (in checked out version)
459 use (l)ocal source (f74e50bd9e55) or (r)emote source (d65e59e952a9)? r
459 use (l)ocal source (f74e50bd9e55) or (r)emote source (d65e59e952a9)? r
460 local changed .hglf/large2 which remote deleted
460 local changed .hglf/large2 which remote deleted
461 use (c)hanged version or (d)elete? c
461 use (c)hanged version or (d)elete? c
462 remote turned local largefile large2 into a normal file
462 remote turned local largefile large2 into a normal file
463 keep (l)argefile or use (n)ormal file? l
463 keep (l)argefile or use (n)ormal file? l
464 largefile large1 has a merge conflict
464 largefile large1 has a merge conflict
465 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
465 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
466 keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or
466 keep (l)ocal ba94c2efe5b7c5e0af8d189295ce00553b0612b7 or
467 take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b? l
467 take (o)ther e5bb990443d6a92aaf7223813720f7566c9dd05b? l
468 2 files updated, 1 files merged, 0 files removed, 0 files unresolved
468 2 files updated, 1 files merged, 0 files removed, 0 files unresolved
469 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
469 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
470
470
471 $ hg -R sub status -A sub/large1
471 $ hg -R sub status -A sub/large1
472 M sub/large1
472 M sub/large1
473 $ cat sub/large1
473 $ cat sub/large1
474 large1 for linear merge (conflict)
474 large1 for linear merge (conflict)
475 $ cat sub/.hglf/large1
475 $ cat sub/.hglf/large1
476 ba94c2efe5b7c5e0af8d189295ce00553b0612b7
476 ba94c2efe5b7c5e0af8d189295ce00553b0612b7
477 $ hg -R sub status -A sub/large2
477 $ hg -R sub status -A sub/large2
478 A sub/large2
478 A sub/large2
479 $ cat sub/large2
479 $ cat sub/large2
480 large2 for linear merge (conflict with normal file)
480 large2 for linear merge (conflict with normal file)
481 $ cat sub/.hglf/large2
481 $ cat sub/.hglf/large2
482 d7591fe9be0f6227d90bddf3e4f52ff41fc1f544
482 d7591fe9be0f6227d90bddf3e4f52ff41fc1f544
483
483
484 $ cd ..
484 $ cd ..
485 $ cd repo
485 $ cd repo
486
486
487 Test that rebase updates largefiles in the working directory even if
487 Test that rebase updates largefiles in the working directory even if
488 it is aborted by conflict.
488 it is aborted by conflict.
489
489
490 $ hg update -q -C 3
490 $ hg update -q -C 3
491 $ cat .hglf/large1
491 $ cat .hglf/large1
492 e5bb990443d6a92aaf7223813720f7566c9dd05b
492 e5bb990443d6a92aaf7223813720f7566c9dd05b
493 $ cat large1
493 $ cat large1
494 large1 in #3
494 large1 in #3
495 $ hg rebase -s 1 -d 3 --keep --config ui.interactive=True <<EOF
495 $ hg rebase -s 1 -d 3 --keep --config ui.interactive=True <<EOF
496 > o
496 > o
497 > EOF
497 > EOF
498 largefile large1 has a merge conflict
498 largefile large1 has a merge conflict
499 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
499 ancestor was 4669e532d5b2c093a78eca010077e708a071bb64
500 keep (l)ocal e5bb990443d6a92aaf7223813720f7566c9dd05b or
500 keep (l)ocal e5bb990443d6a92aaf7223813720f7566c9dd05b or
501 take (o)ther 58e24f733a964da346e2407a2bee99d9001184f5? o
501 take (o)ther 58e24f733a964da346e2407a2bee99d9001184f5? o
502 merging normal1
502 merging normal1
503 warning: conflicts during merge.
503 warning: conflicts during merge.
504 merging normal1 incomplete! (edit conflicts, then use 'hg resolve --mark')
504 merging normal1 incomplete! (edit conflicts, then use 'hg resolve --mark')
505 unresolved conflicts (see hg resolve, then hg rebase --continue)
505 unresolved conflicts (see hg resolve, then hg rebase --continue)
506 [1]
506 [1]
507 $ cat .hglf/large1
507 $ cat .hglf/large1
508 58e24f733a964da346e2407a2bee99d9001184f5
508 58e24f733a964da346e2407a2bee99d9001184f5
509 $ cat large1
509 $ cat large1
510 large1 in #1
510 large1 in #1
511
511
512 $ hg rebase -q --abort
512 $ hg rebase -q --abort
513 rebase aborted
513 rebase aborted
514
514
515 Test that transplant updates largefiles, of which standins are safely
515 Test that transplant updates largefiles, of which standins are safely
516 changed, even if it is aborted by conflict of other.
516 changed, even if it is aborted by conflict of other.
517
517
518 $ hg update -q -C 5
518 $ hg update -q -C 5
519 $ cat .hglf/large1
519 $ cat .hglf/large1
520 e5bb990443d6a92aaf7223813720f7566c9dd05b
520 e5bb990443d6a92aaf7223813720f7566c9dd05b
521 $ cat large1
521 $ cat large1
522 large1 in #3
522 large1 in #3
523 $ hg diff -c 4 .hglf/largeX | grep '^[+-][0-9a-z]'
523 $ hg diff -c 4 .hglf/largeX | grep '^[+-][0-9a-z]'
524 +fa44618ea25181aff4f48b70428294790cec9f61
524 +fa44618ea25181aff4f48b70428294790cec9f61
525 $ hg transplant 4
525 $ hg transplant 4
526 applying 07d6153b5c04
526 applying 07d6153b5c04
527 patching file .hglf/large1
527 patching file .hglf/large1
528 Hunk #1 FAILED at 0
528 Hunk #1 FAILED at 0
529 1 out of 1 hunks FAILED -- saving rejects to file .hglf/large1.rej
529 1 out of 1 hunks FAILED -- saving rejects to file .hglf/large1.rej
530 patch failed to apply
530 patch failed to apply
531 abort: fix up the merge and run hg transplant --continue
531 abort: fix up the merge and run hg transplant --continue
532 [255]
532 [255]
533 $ hg status -A large1
533 $ hg status -A large1
534 C large1
534 C large1
535 $ cat .hglf/large1
535 $ cat .hglf/large1
536 e5bb990443d6a92aaf7223813720f7566c9dd05b
536 e5bb990443d6a92aaf7223813720f7566c9dd05b
537 $ cat large1
537 $ cat large1
538 large1 in #3
538 large1 in #3
539 $ hg status -A largeX
539 $ hg status -A largeX
540 A largeX
540 A largeX
541 $ cat .hglf/largeX
541 $ cat .hglf/largeX
542 fa44618ea25181aff4f48b70428294790cec9f61
542 fa44618ea25181aff4f48b70428294790cec9f61
543 $ cat largeX
543 $ cat largeX
544 largeX
544 largeX
545
545
546 Test that "hg status" doesn't show removal of largefiles not managed
547 in the target context.
548
549 $ hg update -q -C 4
550 $ hg remove largeX
551 $ hg status -A largeX
552 R largeX
553 $ hg status -A --rev '.^1' largeX
554
546 $ cd ..
555 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now