##// END OF EJS Templates
merge: delay debug messages for merge actions...
Mads Kiilerich -
r18541:5ed6a375 default
parent child Browse files
Show More
@@ -1,1178 +1,1178 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 '''Overridden Mercurial commands and functions for the largefiles extension'''
9 '''Overridden Mercurial commands and functions for the largefiles extension'''
10
10
11 import os
11 import os
12 import copy
12 import copy
13
13
14 from mercurial import hg, commands, util, cmdutil, scmutil, match as match_, \
14 from mercurial import hg, commands, util, cmdutil, scmutil, match as match_, \
15 node, archival, error, merge, discovery
15 node, archival, error, merge, discovery
16 from mercurial.i18n import _
16 from mercurial.i18n import _
17 from mercurial.node import hex
17 from mercurial.node import hex
18 from hgext import rebase
18 from hgext import rebase
19
19
20 import lfutil
20 import lfutil
21 import lfcommands
21 import lfcommands
22
22
23 # -- Utility functions: commonly/repeatedly needed functionality ---------------
23 # -- Utility functions: commonly/repeatedly needed functionality ---------------
24
24
25 def installnormalfilesmatchfn(manifest):
25 def installnormalfilesmatchfn(manifest):
26 '''overrides scmutil.match so that the matcher it returns will ignore all
26 '''overrides scmutil.match so that the matcher it returns will ignore all
27 largefiles'''
27 largefiles'''
28 oldmatch = None # for the closure
28 oldmatch = None # for the closure
29 def overridematch(ctx, pats=[], opts={}, globbed=False,
29 def overridematch(ctx, pats=[], opts={}, globbed=False,
30 default='relpath'):
30 default='relpath'):
31 match = oldmatch(ctx, pats, opts, globbed, default)
31 match = oldmatch(ctx, pats, opts, globbed, default)
32 m = copy.copy(match)
32 m = copy.copy(match)
33 notlfile = lambda f: not (lfutil.isstandin(f) or lfutil.standin(f) in
33 notlfile = lambda f: not (lfutil.isstandin(f) or lfutil.standin(f) in
34 manifest)
34 manifest)
35 m._files = filter(notlfile, m._files)
35 m._files = filter(notlfile, m._files)
36 m._fmap = set(m._files)
36 m._fmap = set(m._files)
37 origmatchfn = m.matchfn
37 origmatchfn = m.matchfn
38 m.matchfn = lambda f: notlfile(f) and origmatchfn(f) or None
38 m.matchfn = lambda f: notlfile(f) and origmatchfn(f) or None
39 return m
39 return m
40 oldmatch = installmatchfn(overridematch)
40 oldmatch = installmatchfn(overridematch)
41
41
42 def installmatchfn(f):
42 def installmatchfn(f):
43 oldmatch = scmutil.match
43 oldmatch = scmutil.match
44 setattr(f, 'oldmatch', oldmatch)
44 setattr(f, 'oldmatch', oldmatch)
45 scmutil.match = f
45 scmutil.match = f
46 return oldmatch
46 return oldmatch
47
47
48 def restorematchfn():
48 def restorematchfn():
49 '''restores scmutil.match to what it was before installnormalfilesmatchfn
49 '''restores scmutil.match to what it was before installnormalfilesmatchfn
50 was called. no-op if scmutil.match is its original function.
50 was called. no-op if scmutil.match is its original function.
51
51
52 Note that n calls to installnormalfilesmatchfn will require n calls to
52 Note that n calls to installnormalfilesmatchfn will require n calls to
53 restore matchfn to reverse'''
53 restore matchfn to reverse'''
54 scmutil.match = getattr(scmutil.match, 'oldmatch', scmutil.match)
54 scmutil.match = getattr(scmutil.match, 'oldmatch', scmutil.match)
55
55
56 def addlargefiles(ui, repo, *pats, **opts):
56 def addlargefiles(ui, repo, *pats, **opts):
57 large = opts.pop('large', None)
57 large = opts.pop('large', None)
58 lfsize = lfutil.getminsize(
58 lfsize = lfutil.getminsize(
59 ui, lfutil.islfilesrepo(repo), opts.pop('lfsize', None))
59 ui, lfutil.islfilesrepo(repo), opts.pop('lfsize', None))
60
60
61 lfmatcher = None
61 lfmatcher = None
62 if lfutil.islfilesrepo(repo):
62 if lfutil.islfilesrepo(repo):
63 lfpats = ui.configlist(lfutil.longname, 'patterns', default=[])
63 lfpats = ui.configlist(lfutil.longname, 'patterns', default=[])
64 if lfpats:
64 if lfpats:
65 lfmatcher = match_.match(repo.root, '', list(lfpats))
65 lfmatcher = match_.match(repo.root, '', list(lfpats))
66
66
67 lfnames = []
67 lfnames = []
68 m = scmutil.match(repo[None], pats, opts)
68 m = scmutil.match(repo[None], pats, opts)
69 m.bad = lambda x, y: None
69 m.bad = lambda x, y: None
70 wctx = repo[None]
70 wctx = repo[None]
71 for f in repo.walk(m):
71 for f in repo.walk(m):
72 exact = m.exact(f)
72 exact = m.exact(f)
73 lfile = lfutil.standin(f) in wctx
73 lfile = lfutil.standin(f) in wctx
74 nfile = f in wctx
74 nfile = f in wctx
75 exists = lfile or nfile
75 exists = lfile or nfile
76
76
77 # Don't warn the user when they attempt to add a normal tracked file.
77 # Don't warn the user when they attempt to add a normal tracked file.
78 # The normal add code will do that for us.
78 # The normal add code will do that for us.
79 if exact and exists:
79 if exact and exists:
80 if lfile:
80 if lfile:
81 ui.warn(_('%s already a largefile\n') % f)
81 ui.warn(_('%s already a largefile\n') % f)
82 continue
82 continue
83
83
84 if (exact or not exists) and not lfutil.isstandin(f):
84 if (exact or not exists) and not lfutil.isstandin(f):
85 wfile = repo.wjoin(f)
85 wfile = repo.wjoin(f)
86
86
87 # In case the file was removed previously, but not committed
87 # In case the file was removed previously, but not committed
88 # (issue3507)
88 # (issue3507)
89 if not os.path.exists(wfile):
89 if not os.path.exists(wfile):
90 continue
90 continue
91
91
92 abovemin = (lfsize and
92 abovemin = (lfsize and
93 os.lstat(wfile).st_size >= lfsize * 1024 * 1024)
93 os.lstat(wfile).st_size >= lfsize * 1024 * 1024)
94 if large or abovemin or (lfmatcher and lfmatcher(f)):
94 if large or abovemin or (lfmatcher and lfmatcher(f)):
95 lfnames.append(f)
95 lfnames.append(f)
96 if ui.verbose or not exact:
96 if ui.verbose or not exact:
97 ui.status(_('adding %s as a largefile\n') % m.rel(f))
97 ui.status(_('adding %s as a largefile\n') % m.rel(f))
98
98
99 bad = []
99 bad = []
100 standins = []
100 standins = []
101
101
102 # Need to lock, otherwise there could be a race condition between
102 # Need to lock, otherwise there could be a race condition between
103 # when standins are created and added to the repo.
103 # when standins are created and added to the repo.
104 wlock = repo.wlock()
104 wlock = repo.wlock()
105 try:
105 try:
106 if not opts.get('dry_run'):
106 if not opts.get('dry_run'):
107 lfdirstate = lfutil.openlfdirstate(ui, repo)
107 lfdirstate = lfutil.openlfdirstate(ui, repo)
108 for f in lfnames:
108 for f in lfnames:
109 standinname = lfutil.standin(f)
109 standinname = lfutil.standin(f)
110 lfutil.writestandin(repo, standinname, hash='',
110 lfutil.writestandin(repo, standinname, hash='',
111 executable=lfutil.getexecutable(repo.wjoin(f)))
111 executable=lfutil.getexecutable(repo.wjoin(f)))
112 standins.append(standinname)
112 standins.append(standinname)
113 if lfdirstate[f] == 'r':
113 if lfdirstate[f] == 'r':
114 lfdirstate.normallookup(f)
114 lfdirstate.normallookup(f)
115 else:
115 else:
116 lfdirstate.add(f)
116 lfdirstate.add(f)
117 lfdirstate.write()
117 lfdirstate.write()
118 bad += [lfutil.splitstandin(f)
118 bad += [lfutil.splitstandin(f)
119 for f in repo[None].add(standins)
119 for f in repo[None].add(standins)
120 if f in m.files()]
120 if f in m.files()]
121 finally:
121 finally:
122 wlock.release()
122 wlock.release()
123 return bad
123 return bad
124
124
125 def removelargefiles(ui, repo, *pats, **opts):
125 def removelargefiles(ui, repo, *pats, **opts):
126 after = opts.get('after')
126 after = opts.get('after')
127 if not pats and not after:
127 if not pats and not after:
128 raise util.Abort(_('no files specified'))
128 raise util.Abort(_('no files specified'))
129 m = scmutil.match(repo[None], pats, opts)
129 m = scmutil.match(repo[None], pats, opts)
130 try:
130 try:
131 repo.lfstatus = True
131 repo.lfstatus = True
132 s = repo.status(match=m, clean=True)
132 s = repo.status(match=m, clean=True)
133 finally:
133 finally:
134 repo.lfstatus = False
134 repo.lfstatus = False
135 manifest = repo[None].manifest()
135 manifest = repo[None].manifest()
136 modified, added, deleted, clean = [[f for f in list
136 modified, added, deleted, clean = [[f for f in list
137 if lfutil.standin(f) in manifest]
137 if lfutil.standin(f) in manifest]
138 for list in [s[0], s[1], s[3], s[6]]]
138 for list in [s[0], s[1], s[3], s[6]]]
139
139
140 def warn(files, msg):
140 def warn(files, msg):
141 for f in files:
141 for f in files:
142 ui.warn(msg % m.rel(f))
142 ui.warn(msg % m.rel(f))
143 return int(len(files) > 0)
143 return int(len(files) > 0)
144
144
145 result = 0
145 result = 0
146
146
147 if after:
147 if after:
148 remove, forget = deleted, []
148 remove, forget = deleted, []
149 result = warn(modified + added + clean,
149 result = warn(modified + added + clean,
150 _('not removing %s: file still exists\n'))
150 _('not removing %s: file still exists\n'))
151 else:
151 else:
152 remove, forget = deleted + clean, []
152 remove, forget = deleted + clean, []
153 result = warn(modified, _('not removing %s: file is modified (use -f'
153 result = warn(modified, _('not removing %s: file is modified (use -f'
154 ' to force removal)\n'))
154 ' to force removal)\n'))
155 result = warn(added, _('not removing %s: file has been marked for add'
155 result = warn(added, _('not removing %s: file has been marked for add'
156 ' (use forget to undo)\n')) or result
156 ' (use forget to undo)\n')) or result
157
157
158 for f in sorted(remove + forget):
158 for f in sorted(remove + forget):
159 if ui.verbose or not m.exact(f):
159 if ui.verbose or not m.exact(f):
160 ui.status(_('removing %s\n') % m.rel(f))
160 ui.status(_('removing %s\n') % m.rel(f))
161
161
162 # Need to lock because standin files are deleted then removed from the
162 # Need to lock because standin files are deleted then removed from the
163 # repository and we could race in-between.
163 # repository and we could race in-between.
164 wlock = repo.wlock()
164 wlock = repo.wlock()
165 try:
165 try:
166 lfdirstate = lfutil.openlfdirstate(ui, repo)
166 lfdirstate = lfutil.openlfdirstate(ui, repo)
167 for f in remove:
167 for f in remove:
168 if not after:
168 if not after:
169 # If this is being called by addremove, notify the user that we
169 # If this is being called by addremove, notify the user that we
170 # are removing the file.
170 # are removing the file.
171 if getattr(repo, "_isaddremove", False):
171 if getattr(repo, "_isaddremove", False):
172 ui.status(_('removing %s\n') % f)
172 ui.status(_('removing %s\n') % f)
173 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
173 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
174 lfdirstate.remove(f)
174 lfdirstate.remove(f)
175 lfdirstate.write()
175 lfdirstate.write()
176 forget = [lfutil.standin(f) for f in forget]
176 forget = [lfutil.standin(f) for f in forget]
177 remove = [lfutil.standin(f) for f in remove]
177 remove = [lfutil.standin(f) for f in remove]
178 repo[None].forget(forget)
178 repo[None].forget(forget)
179 # If this is being called by addremove, let the original addremove
179 # If this is being called by addremove, let the original addremove
180 # function handle this.
180 # function handle this.
181 if not getattr(repo, "_isaddremove", False):
181 if not getattr(repo, "_isaddremove", False):
182 for f in remove:
182 for f in remove:
183 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
183 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
184 repo[None].forget(remove)
184 repo[None].forget(remove)
185 finally:
185 finally:
186 wlock.release()
186 wlock.release()
187
187
188 return result
188 return result
189
189
190 # For overriding mercurial.hgweb.webcommands so that largefiles will
190 # For overriding mercurial.hgweb.webcommands so that largefiles will
191 # appear at their right place in the manifests.
191 # appear at their right place in the manifests.
192 def decodepath(orig, path):
192 def decodepath(orig, path):
193 return lfutil.splitstandin(path) or path
193 return lfutil.splitstandin(path) or path
194
194
195 # -- Wrappers: modify existing commands --------------------------------
195 # -- Wrappers: modify existing commands --------------------------------
196
196
197 # Add works by going through the files that the user wanted to add and
197 # Add works by going through the files that the user wanted to add and
198 # checking if they should be added as largefiles. Then it makes a new
198 # checking if they should be added as largefiles. Then it makes a new
199 # matcher which matches only the normal files and runs the original
199 # matcher which matches only the normal files and runs the original
200 # version of add.
200 # version of add.
201 def overrideadd(orig, ui, repo, *pats, **opts):
201 def overrideadd(orig, ui, repo, *pats, **opts):
202 normal = opts.pop('normal')
202 normal = opts.pop('normal')
203 if normal:
203 if normal:
204 if opts.get('large'):
204 if opts.get('large'):
205 raise util.Abort(_('--normal cannot be used with --large'))
205 raise util.Abort(_('--normal cannot be used with --large'))
206 return orig(ui, repo, *pats, **opts)
206 return orig(ui, repo, *pats, **opts)
207 bad = addlargefiles(ui, repo, *pats, **opts)
207 bad = addlargefiles(ui, repo, *pats, **opts)
208 installnormalfilesmatchfn(repo[None].manifest())
208 installnormalfilesmatchfn(repo[None].manifest())
209 result = orig(ui, repo, *pats, **opts)
209 result = orig(ui, repo, *pats, **opts)
210 restorematchfn()
210 restorematchfn()
211
211
212 return (result == 1 or bad) and 1 or 0
212 return (result == 1 or bad) and 1 or 0
213
213
214 def overrideremove(orig, ui, repo, *pats, **opts):
214 def overrideremove(orig, ui, repo, *pats, **opts):
215 installnormalfilesmatchfn(repo[None].manifest())
215 installnormalfilesmatchfn(repo[None].manifest())
216 result = orig(ui, repo, *pats, **opts)
216 result = orig(ui, repo, *pats, **opts)
217 restorematchfn()
217 restorematchfn()
218 return removelargefiles(ui, repo, *pats, **opts) or result
218 return removelargefiles(ui, repo, *pats, **opts) or result
219
219
220 def overridestatusfn(orig, repo, rev2, **opts):
220 def overridestatusfn(orig, repo, rev2, **opts):
221 try:
221 try:
222 repo._repo.lfstatus = True
222 repo._repo.lfstatus = True
223 return orig(repo, rev2, **opts)
223 return orig(repo, rev2, **opts)
224 finally:
224 finally:
225 repo._repo.lfstatus = False
225 repo._repo.lfstatus = False
226
226
227 def overridestatus(orig, ui, repo, *pats, **opts):
227 def overridestatus(orig, ui, repo, *pats, **opts):
228 try:
228 try:
229 repo.lfstatus = True
229 repo.lfstatus = True
230 return orig(ui, repo, *pats, **opts)
230 return orig(ui, repo, *pats, **opts)
231 finally:
231 finally:
232 repo.lfstatus = False
232 repo.lfstatus = False
233
233
234 def overridedirty(orig, repo, ignoreupdate=False):
234 def overridedirty(orig, repo, ignoreupdate=False):
235 try:
235 try:
236 repo._repo.lfstatus = True
236 repo._repo.lfstatus = True
237 return orig(repo, ignoreupdate)
237 return orig(repo, ignoreupdate)
238 finally:
238 finally:
239 repo._repo.lfstatus = False
239 repo._repo.lfstatus = False
240
240
241 def overridelog(orig, ui, repo, *pats, **opts):
241 def overridelog(orig, ui, repo, *pats, **opts):
242 def overridematch(ctx, pats=[], opts={}, globbed=False,
242 def overridematch(ctx, pats=[], opts={}, globbed=False,
243 default='relpath'):
243 default='relpath'):
244 """Matcher that merges root directory with .hglf, suitable for log.
244 """Matcher that merges root directory with .hglf, suitable for log.
245 It is still possible to match .hglf directly.
245 It is still possible to match .hglf directly.
246 For any listed files run log on the standin too.
246 For any listed files run log on the standin too.
247 matchfn tries both the given filename and with .hglf stripped.
247 matchfn tries both the given filename and with .hglf stripped.
248 """
248 """
249 match = oldmatch(ctx, pats, opts, globbed, default)
249 match = oldmatch(ctx, pats, opts, globbed, default)
250 m = copy.copy(match)
250 m = copy.copy(match)
251 standins = [lfutil.standin(f) for f in m._files]
251 standins = [lfutil.standin(f) for f in m._files]
252 m._files.extend(standins)
252 m._files.extend(standins)
253 m._fmap = set(m._files)
253 m._fmap = set(m._files)
254 origmatchfn = m.matchfn
254 origmatchfn = m.matchfn
255 def lfmatchfn(f):
255 def lfmatchfn(f):
256 lf = lfutil.splitstandin(f)
256 lf = lfutil.splitstandin(f)
257 if lf is not None and origmatchfn(lf):
257 if lf is not None and origmatchfn(lf):
258 return True
258 return True
259 r = origmatchfn(f)
259 r = origmatchfn(f)
260 return r
260 return r
261 m.matchfn = lfmatchfn
261 m.matchfn = lfmatchfn
262 return m
262 return m
263 oldmatch = installmatchfn(overridematch)
263 oldmatch = installmatchfn(overridematch)
264 try:
264 try:
265 repo.lfstatus = True
265 repo.lfstatus = True
266 return orig(ui, repo, *pats, **opts)
266 return orig(ui, repo, *pats, **opts)
267 finally:
267 finally:
268 repo.lfstatus = False
268 repo.lfstatus = False
269 restorematchfn()
269 restorematchfn()
270
270
271 def overrideverify(orig, ui, repo, *pats, **opts):
271 def overrideverify(orig, ui, repo, *pats, **opts):
272 large = opts.pop('large', False)
272 large = opts.pop('large', False)
273 all = opts.pop('lfa', False)
273 all = opts.pop('lfa', False)
274 contents = opts.pop('lfc', False)
274 contents = opts.pop('lfc', False)
275
275
276 result = orig(ui, repo, *pats, **opts)
276 result = orig(ui, repo, *pats, **opts)
277 if large:
277 if large:
278 result = result or lfcommands.verifylfiles(ui, repo, all, contents)
278 result = result or lfcommands.verifylfiles(ui, repo, all, contents)
279 return result
279 return result
280
280
281 def overridedebugstate(orig, ui, repo, *pats, **opts):
281 def overridedebugstate(orig, ui, repo, *pats, **opts):
282 large = opts.pop('large', False)
282 large = opts.pop('large', False)
283 if large:
283 if large:
284 lfcommands.debugdirstate(ui, repo)
284 lfcommands.debugdirstate(ui, repo)
285 else:
285 else:
286 orig(ui, repo, *pats, **opts)
286 orig(ui, repo, *pats, **opts)
287
287
288 # Override needs to refresh standins so that update's normal merge
288 # Override needs to refresh standins so that update's normal merge
289 # will go through properly. Then the other update hook (overriding repo.update)
289 # will go through properly. Then the other update hook (overriding repo.update)
290 # will get the new files. Filemerge is also overridden so that the merge
290 # will get the new files. Filemerge is also overridden so that the merge
291 # will merge standins correctly.
291 # will merge standins correctly.
292 def overrideupdate(orig, ui, repo, *pats, **opts):
292 def overrideupdate(orig, ui, repo, *pats, **opts):
293 lfdirstate = lfutil.openlfdirstate(ui, repo)
293 lfdirstate = lfutil.openlfdirstate(ui, repo)
294 s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
294 s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
295 False, False)
295 False, False)
296 (unsure, modified, added, removed, missing, unknown, ignored, clean) = s
296 (unsure, modified, added, removed, missing, unknown, ignored, clean) = s
297
297
298 # Need to lock between the standins getting updated and their
298 # Need to lock between the standins getting updated and their
299 # largefiles getting updated
299 # largefiles getting updated
300 wlock = repo.wlock()
300 wlock = repo.wlock()
301 try:
301 try:
302 if opts['check']:
302 if opts['check']:
303 mod = len(modified) > 0
303 mod = len(modified) > 0
304 for lfile in unsure:
304 for lfile in unsure:
305 standin = lfutil.standin(lfile)
305 standin = lfutil.standin(lfile)
306 if repo['.'][standin].data().strip() != \
306 if repo['.'][standin].data().strip() != \
307 lfutil.hashfile(repo.wjoin(lfile)):
307 lfutil.hashfile(repo.wjoin(lfile)):
308 mod = True
308 mod = True
309 else:
309 else:
310 lfdirstate.normal(lfile)
310 lfdirstate.normal(lfile)
311 lfdirstate.write()
311 lfdirstate.write()
312 if mod:
312 if mod:
313 raise util.Abort(_('uncommitted local changes'))
313 raise util.Abort(_('uncommitted local changes'))
314 # XXX handle removed differently
314 # XXX handle removed differently
315 if not opts['clean']:
315 if not opts['clean']:
316 for lfile in unsure + modified + added:
316 for lfile in unsure + modified + added:
317 lfutil.updatestandin(repo, lfutil.standin(lfile))
317 lfutil.updatestandin(repo, lfutil.standin(lfile))
318 finally:
318 finally:
319 wlock.release()
319 wlock.release()
320 return orig(ui, repo, *pats, **opts)
320 return orig(ui, repo, *pats, **opts)
321
321
322 # Before starting the manifest merge, merge.updates will call
322 # Before starting the manifest merge, merge.updates will call
323 # _checkunknown to check if there are any files in the merged-in
323 # _checkunknown to check if there are any files in the merged-in
324 # changeset that collide with unknown files in the working copy.
324 # changeset that collide with unknown files in the working copy.
325 #
325 #
326 # The largefiles are seen as unknown, so this prevents us from merging
326 # The largefiles are seen as unknown, so this prevents us from merging
327 # in a file 'foo' if we already have a largefile with the same name.
327 # in a file 'foo' if we already have a largefile with the same name.
328 #
328 #
329 # The overridden function filters the unknown files by removing any
329 # The overridden function filters the unknown files by removing any
330 # largefiles. This makes the merge proceed and we can then handle this
330 # largefiles. This makes the merge proceed and we can then handle this
331 # case further in the overridden manifestmerge function below.
331 # case further in the overridden manifestmerge function below.
332 def overridecheckunknownfile(origfn, repo, wctx, mctx, f):
332 def overridecheckunknownfile(origfn, repo, wctx, mctx, f):
333 if lfutil.standin(f) in wctx:
333 if lfutil.standin(f) in wctx:
334 return False
334 return False
335 return origfn(repo, wctx, mctx, f)
335 return origfn(repo, wctx, mctx, f)
336
336
337 # The manifest merge handles conflicts on the manifest level. We want
337 # The manifest merge handles conflicts on the manifest level. We want
338 # to handle changes in largefile-ness of files at this level too.
338 # to handle changes in largefile-ness of files at this level too.
339 #
339 #
340 # The strategy is to run the original manifestmerge and then process
340 # The strategy is to run the original manifestmerge and then process
341 # the action list it outputs. There are two cases we need to deal with:
341 # the action list it outputs. There are two cases we need to deal with:
342 #
342 #
343 # 1. Normal file in p1, largefile in p2. Here the largefile is
343 # 1. Normal file in p1, largefile in p2. Here the largefile is
344 # detected via its standin file, which will enter the working copy
344 # detected via its standin file, which will enter the working copy
345 # with a "get" action. It is not "merge" since the standin is all
345 # with a "get" action. It is not "merge" since the standin is all
346 # Mercurial is concerned with at this level -- the link to the
346 # Mercurial is concerned with at this level -- the link to the
347 # existing normal file is not relevant here.
347 # existing normal file is not relevant here.
348 #
348 #
349 # 2. Largefile in p1, normal file in p2. Here we get a "merge" action
349 # 2. Largefile in p1, normal file in p2. Here we get a "merge" action
350 # since the largefile will be present in the working copy and
350 # since the largefile will be present in the working copy and
351 # different from the normal file in p2. Mercurial therefore
351 # different from the normal file in p2. Mercurial therefore
352 # triggers a merge action.
352 # triggers a merge action.
353 #
353 #
354 # In both cases, we prompt the user and emit new actions to either
354 # In both cases, we prompt the user and emit new actions to either
355 # remove the standin (if the normal file was kept) or to remove the
355 # remove the standin (if the normal file was kept) or to remove the
356 # normal file and get the standin (if the largefile was kept). The
356 # normal file and get the standin (if the largefile was kept). The
357 # default prompt answer is to use the largefile version since it was
357 # default prompt answer is to use the largefile version since it was
358 # presumably changed on purpose.
358 # presumably changed on purpose.
359 #
359 #
360 # Finally, the merge.applyupdates function will then take care of
360 # Finally, the merge.applyupdates function will then take care of
361 # writing the files into the working copy and lfcommands.updatelfiles
361 # writing the files into the working copy and lfcommands.updatelfiles
362 # will update the largefiles.
362 # will update the largefiles.
363 def overridemanifestmerge(origfn, repo, p1, p2, pa, overwrite, partial):
363 def overridemanifestmerge(origfn, repo, p1, p2, pa, overwrite, partial):
364 actions = origfn(repo, p1, p2, pa, overwrite, partial)
364 actions = origfn(repo, p1, p2, pa, overwrite, partial)
365 processed = []
365 processed = []
366
366
367 for action in actions:
367 for action in actions:
368 if overwrite:
368 if overwrite:
369 processed.append(action)
369 processed.append(action)
370 continue
370 continue
371 f, m, args = action
371 f, m, args, msg = action
372
372
373 choices = (_('&Largefile'), _('&Normal file'))
373 choices = (_('&Largefile'), _('&Normal file'))
374 if m == "g" and lfutil.splitstandin(f) in p1 and f in p2:
374 if m == "g" and lfutil.splitstandin(f) in p1 and f in p2:
375 # Case 1: normal file in the working copy, largefile in
375 # Case 1: normal file in the working copy, largefile in
376 # the second parent
376 # the second parent
377 lfile = lfutil.splitstandin(f)
377 lfile = lfutil.splitstandin(f)
378 standin = f
378 standin = f
379 msg = _('%s has been turned into a largefile\n'
379 msg = _('%s has been turned into a largefile\n'
380 'use (l)argefile or keep as (n)ormal file?') % lfile
380 'use (l)argefile or keep as (n)ormal file?') % lfile
381 if repo.ui.promptchoice(msg, choices, 0) == 0:
381 if repo.ui.promptchoice(msg, choices, 0) == 0:
382 processed.append((lfile, "r", None))
382 processed.append((lfile, "r", None, msg))
383 processed.append((standin, "g", (p2.flags(standin),)))
383 processed.append((standin, "g", (p2.flags(standin),), msg))
384 else:
384 else:
385 processed.append((standin, "r", None))
385 processed.append((standin, "r", None, msg))
386 elif m == "g" and lfutil.standin(f) in p1 and f in p2:
386 elif m == "g" and lfutil.standin(f) in p1 and f in p2:
387 # Case 2: largefile in the working copy, normal file in
387 # Case 2: largefile in the working copy, normal file in
388 # the second parent
388 # the second parent
389 standin = lfutil.standin(f)
389 standin = lfutil.standin(f)
390 lfile = f
390 lfile = f
391 msg = _('%s has been turned into a normal file\n'
391 msg = _('%s has been turned into a normal file\n'
392 'keep as (l)argefile or use (n)ormal file?') % lfile
392 'keep as (l)argefile or use (n)ormal file?') % lfile
393 if repo.ui.promptchoice(msg, choices, 0) == 0:
393 if repo.ui.promptchoice(msg, choices, 0) == 0:
394 processed.append((lfile, "r", None))
394 processed.append((lfile, "r", None, msg))
395 else:
395 else:
396 processed.append((standin, "r", None))
396 processed.append((standin, "r", None, msg))
397 processed.append((lfile, "g", (p2.flags(lfile),)))
397 processed.append((lfile, "g", (p2.flags(lfile),), msg))
398 else:
398 else:
399 processed.append(action)
399 processed.append(action)
400
400
401 return processed
401 return processed
402
402
403 # Override filemerge to prompt the user about how they wish to merge
403 # Override filemerge to prompt the user about how they wish to merge
404 # largefiles. This will handle identical edits, and copy/rename +
404 # largefiles. This will handle identical edits, and copy/rename +
405 # edit without prompting the user.
405 # edit without prompting the user.
406 def overridefilemerge(origfn, repo, mynode, orig, fcd, fco, fca):
406 def overridefilemerge(origfn, repo, mynode, orig, fcd, fco, fca):
407 # Use better variable names here. Because this is a wrapper we cannot
407 # Use better variable names here. Because this is a wrapper we cannot
408 # change the variable names in the function declaration.
408 # change the variable names in the function declaration.
409 fcdest, fcother, fcancestor = fcd, fco, fca
409 fcdest, fcother, fcancestor = fcd, fco, fca
410 if not lfutil.isstandin(orig):
410 if not lfutil.isstandin(orig):
411 return origfn(repo, mynode, orig, fcdest, fcother, fcancestor)
411 return origfn(repo, mynode, orig, fcdest, fcother, fcancestor)
412 else:
412 else:
413 if not fcother.cmp(fcdest): # files identical?
413 if not fcother.cmp(fcdest): # files identical?
414 return None
414 return None
415
415
416 # backwards, use working dir parent as ancestor
416 # backwards, use working dir parent as ancestor
417 if fcancestor == fcother:
417 if fcancestor == fcother:
418 fcancestor = fcdest.parents()[0]
418 fcancestor = fcdest.parents()[0]
419
419
420 if orig != fcother.path():
420 if orig != fcother.path():
421 repo.ui.status(_('merging %s and %s to %s\n')
421 repo.ui.status(_('merging %s and %s to %s\n')
422 % (lfutil.splitstandin(orig),
422 % (lfutil.splitstandin(orig),
423 lfutil.splitstandin(fcother.path()),
423 lfutil.splitstandin(fcother.path()),
424 lfutil.splitstandin(fcdest.path())))
424 lfutil.splitstandin(fcdest.path())))
425 else:
425 else:
426 repo.ui.status(_('merging %s\n')
426 repo.ui.status(_('merging %s\n')
427 % lfutil.splitstandin(fcdest.path()))
427 % lfutil.splitstandin(fcdest.path()))
428
428
429 if fcancestor.path() != fcother.path() and fcother.data() == \
429 if fcancestor.path() != fcother.path() and fcother.data() == \
430 fcancestor.data():
430 fcancestor.data():
431 return 0
431 return 0
432 if fcancestor.path() != fcdest.path() and fcdest.data() == \
432 if fcancestor.path() != fcdest.path() and fcdest.data() == \
433 fcancestor.data():
433 fcancestor.data():
434 repo.wwrite(fcdest.path(), fcother.data(), fcother.flags())
434 repo.wwrite(fcdest.path(), fcother.data(), fcother.flags())
435 return 0
435 return 0
436
436
437 if repo.ui.promptchoice(_('largefile %s has a merge conflict\n'
437 if repo.ui.promptchoice(_('largefile %s has a merge conflict\n'
438 'keep (l)ocal or take (o)ther?') %
438 'keep (l)ocal or take (o)ther?') %
439 lfutil.splitstandin(orig),
439 lfutil.splitstandin(orig),
440 (_('&Local'), _('&Other')), 0) == 0:
440 (_('&Local'), _('&Other')), 0) == 0:
441 return 0
441 return 0
442 else:
442 else:
443 repo.wwrite(fcdest.path(), fcother.data(), fcother.flags())
443 repo.wwrite(fcdest.path(), fcother.data(), fcother.flags())
444 return 0
444 return 0
445
445
446 # Copy first changes the matchers to match standins instead of
446 # Copy first changes the matchers to match standins instead of
447 # largefiles. Then it overrides util.copyfile in that function it
447 # largefiles. Then it overrides util.copyfile in that function it
448 # checks if the destination largefile already exists. It also keeps a
448 # checks if the destination largefile already exists. It also keeps a
449 # list of copied files so that the largefiles can be copied and the
449 # list of copied files so that the largefiles can be copied and the
450 # dirstate updated.
450 # dirstate updated.
451 def overridecopy(orig, ui, repo, pats, opts, rename=False):
451 def overridecopy(orig, ui, repo, pats, opts, rename=False):
452 # doesn't remove largefile on rename
452 # doesn't remove largefile on rename
453 if len(pats) < 2:
453 if len(pats) < 2:
454 # this isn't legal, let the original function deal with it
454 # this isn't legal, let the original function deal with it
455 return orig(ui, repo, pats, opts, rename)
455 return orig(ui, repo, pats, opts, rename)
456
456
457 def makestandin(relpath):
457 def makestandin(relpath):
458 path = scmutil.canonpath(repo.root, repo.getcwd(), relpath)
458 path = scmutil.canonpath(repo.root, repo.getcwd(), relpath)
459 return os.path.join(repo.wjoin(lfutil.standin(path)))
459 return os.path.join(repo.wjoin(lfutil.standin(path)))
460
460
461 fullpats = scmutil.expandpats(pats)
461 fullpats = scmutil.expandpats(pats)
462 dest = fullpats[-1]
462 dest = fullpats[-1]
463
463
464 if os.path.isdir(dest):
464 if os.path.isdir(dest):
465 if not os.path.isdir(makestandin(dest)):
465 if not os.path.isdir(makestandin(dest)):
466 os.makedirs(makestandin(dest))
466 os.makedirs(makestandin(dest))
467 # This could copy both lfiles and normal files in one command,
467 # This could copy both lfiles and normal files in one command,
468 # but we don't want to do that. First replace their matcher to
468 # but we don't want to do that. First replace their matcher to
469 # only match normal files and run it, then replace it to just
469 # only match normal files and run it, then replace it to just
470 # match largefiles and run it again.
470 # match largefiles and run it again.
471 nonormalfiles = False
471 nonormalfiles = False
472 nolfiles = False
472 nolfiles = False
473 try:
473 try:
474 try:
474 try:
475 installnormalfilesmatchfn(repo[None].manifest())
475 installnormalfilesmatchfn(repo[None].manifest())
476 result = orig(ui, repo, pats, opts, rename)
476 result = orig(ui, repo, pats, opts, rename)
477 except util.Abort, e:
477 except util.Abort, e:
478 if str(e) != _('no files to copy'):
478 if str(e) != _('no files to copy'):
479 raise e
479 raise e
480 else:
480 else:
481 nonormalfiles = True
481 nonormalfiles = True
482 result = 0
482 result = 0
483 finally:
483 finally:
484 restorematchfn()
484 restorematchfn()
485
485
486 # The first rename can cause our current working directory to be removed.
486 # The first rename can cause our current working directory to be removed.
487 # In that case there is nothing left to copy/rename so just quit.
487 # In that case there is nothing left to copy/rename so just quit.
488 try:
488 try:
489 repo.getcwd()
489 repo.getcwd()
490 except OSError:
490 except OSError:
491 return result
491 return result
492
492
493 try:
493 try:
494 try:
494 try:
495 # When we call orig below it creates the standins but we don't add
495 # When we call orig below it creates the standins but we don't add
496 # them to the dir state until later so lock during that time.
496 # them to the dir state until later so lock during that time.
497 wlock = repo.wlock()
497 wlock = repo.wlock()
498
498
499 manifest = repo[None].manifest()
499 manifest = repo[None].manifest()
500 oldmatch = None # for the closure
500 oldmatch = None # for the closure
501 def overridematch(ctx, pats=[], opts={}, globbed=False,
501 def overridematch(ctx, pats=[], opts={}, globbed=False,
502 default='relpath'):
502 default='relpath'):
503 newpats = []
503 newpats = []
504 # The patterns were previously mangled to add the standin
504 # The patterns were previously mangled to add the standin
505 # directory; we need to remove that now
505 # directory; we need to remove that now
506 for pat in pats:
506 for pat in pats:
507 if match_.patkind(pat) is None and lfutil.shortname in pat:
507 if match_.patkind(pat) is None and lfutil.shortname in pat:
508 newpats.append(pat.replace(lfutil.shortname, ''))
508 newpats.append(pat.replace(lfutil.shortname, ''))
509 else:
509 else:
510 newpats.append(pat)
510 newpats.append(pat)
511 match = oldmatch(ctx, newpats, opts, globbed, default)
511 match = oldmatch(ctx, newpats, opts, globbed, default)
512 m = copy.copy(match)
512 m = copy.copy(match)
513 lfile = lambda f: lfutil.standin(f) in manifest
513 lfile = lambda f: lfutil.standin(f) in manifest
514 m._files = [lfutil.standin(f) for f in m._files if lfile(f)]
514 m._files = [lfutil.standin(f) for f in m._files if lfile(f)]
515 m._fmap = set(m._files)
515 m._fmap = set(m._files)
516 origmatchfn = m.matchfn
516 origmatchfn = m.matchfn
517 m.matchfn = lambda f: (lfutil.isstandin(f) and
517 m.matchfn = lambda f: (lfutil.isstandin(f) and
518 (f in manifest) and
518 (f in manifest) and
519 origmatchfn(lfutil.splitstandin(f)) or
519 origmatchfn(lfutil.splitstandin(f)) or
520 None)
520 None)
521 return m
521 return m
522 oldmatch = installmatchfn(overridematch)
522 oldmatch = installmatchfn(overridematch)
523 listpats = []
523 listpats = []
524 for pat in pats:
524 for pat in pats:
525 if match_.patkind(pat) is not None:
525 if match_.patkind(pat) is not None:
526 listpats.append(pat)
526 listpats.append(pat)
527 else:
527 else:
528 listpats.append(makestandin(pat))
528 listpats.append(makestandin(pat))
529
529
530 try:
530 try:
531 origcopyfile = util.copyfile
531 origcopyfile = util.copyfile
532 copiedfiles = []
532 copiedfiles = []
533 def overridecopyfile(src, dest):
533 def overridecopyfile(src, dest):
534 if (lfutil.shortname in src and
534 if (lfutil.shortname in src and
535 dest.startswith(repo.wjoin(lfutil.shortname))):
535 dest.startswith(repo.wjoin(lfutil.shortname))):
536 destlfile = dest.replace(lfutil.shortname, '')
536 destlfile = dest.replace(lfutil.shortname, '')
537 if not opts['force'] and os.path.exists(destlfile):
537 if not opts['force'] and os.path.exists(destlfile):
538 raise IOError('',
538 raise IOError('',
539 _('destination largefile already exists'))
539 _('destination largefile already exists'))
540 copiedfiles.append((src, dest))
540 copiedfiles.append((src, dest))
541 origcopyfile(src, dest)
541 origcopyfile(src, dest)
542
542
543 util.copyfile = overridecopyfile
543 util.copyfile = overridecopyfile
544 result += orig(ui, repo, listpats, opts, rename)
544 result += orig(ui, repo, listpats, opts, rename)
545 finally:
545 finally:
546 util.copyfile = origcopyfile
546 util.copyfile = origcopyfile
547
547
548 lfdirstate = lfutil.openlfdirstate(ui, repo)
548 lfdirstate = lfutil.openlfdirstate(ui, repo)
549 for (src, dest) in copiedfiles:
549 for (src, dest) in copiedfiles:
550 if (lfutil.shortname in src and
550 if (lfutil.shortname in src and
551 dest.startswith(repo.wjoin(lfutil.shortname))):
551 dest.startswith(repo.wjoin(lfutil.shortname))):
552 srclfile = src.replace(repo.wjoin(lfutil.standin('')), '')
552 srclfile = src.replace(repo.wjoin(lfutil.standin('')), '')
553 destlfile = dest.replace(repo.wjoin(lfutil.standin('')), '')
553 destlfile = dest.replace(repo.wjoin(lfutil.standin('')), '')
554 destlfiledir = os.path.dirname(repo.wjoin(destlfile)) or '.'
554 destlfiledir = os.path.dirname(repo.wjoin(destlfile)) or '.'
555 if not os.path.isdir(destlfiledir):
555 if not os.path.isdir(destlfiledir):
556 os.makedirs(destlfiledir)
556 os.makedirs(destlfiledir)
557 if rename:
557 if rename:
558 os.rename(repo.wjoin(srclfile), repo.wjoin(destlfile))
558 os.rename(repo.wjoin(srclfile), repo.wjoin(destlfile))
559 lfdirstate.remove(srclfile)
559 lfdirstate.remove(srclfile)
560 else:
560 else:
561 util.copyfile(repo.wjoin(srclfile),
561 util.copyfile(repo.wjoin(srclfile),
562 repo.wjoin(destlfile))
562 repo.wjoin(destlfile))
563
563
564 lfdirstate.add(destlfile)
564 lfdirstate.add(destlfile)
565 lfdirstate.write()
565 lfdirstate.write()
566 except util.Abort, e:
566 except util.Abort, e:
567 if str(e) != _('no files to copy'):
567 if str(e) != _('no files to copy'):
568 raise e
568 raise e
569 else:
569 else:
570 nolfiles = True
570 nolfiles = True
571 finally:
571 finally:
572 restorematchfn()
572 restorematchfn()
573 wlock.release()
573 wlock.release()
574
574
575 if nolfiles and nonormalfiles:
575 if nolfiles and nonormalfiles:
576 raise util.Abort(_('no files to copy'))
576 raise util.Abort(_('no files to copy'))
577
577
578 return result
578 return result
579
579
580 # When the user calls revert, we have to be careful to not revert any
580 # When the user calls revert, we have to be careful to not revert any
581 # changes to other largefiles accidentally. This means we have to keep
581 # changes to other largefiles accidentally. This means we have to keep
582 # track of the largefiles that are being reverted so we only pull down
582 # track of the largefiles that are being reverted so we only pull down
583 # the necessary largefiles.
583 # the necessary largefiles.
584 #
584 #
585 # Standins are only updated (to match the hash of largefiles) before
585 # Standins are only updated (to match the hash of largefiles) before
586 # commits. Update the standins then run the original revert, changing
586 # commits. Update the standins then run the original revert, changing
587 # the matcher to hit standins instead of largefiles. Based on the
587 # the matcher to hit standins instead of largefiles. Based on the
588 # resulting standins update the largefiles. Then return the standins
588 # resulting standins update the largefiles. Then return the standins
589 # to their proper state
589 # to their proper state
590 def overriderevert(orig, ui, repo, *pats, **opts):
590 def overriderevert(orig, ui, repo, *pats, **opts):
591 # Because we put the standins in a bad state (by updating them)
591 # Because we put the standins in a bad state (by updating them)
592 # and then return them to a correct state we need to lock to
592 # and then return them to a correct state we need to lock to
593 # prevent others from changing them in their incorrect state.
593 # prevent others from changing them in their incorrect state.
594 wlock = repo.wlock()
594 wlock = repo.wlock()
595 try:
595 try:
596 lfdirstate = lfutil.openlfdirstate(ui, repo)
596 lfdirstate = lfutil.openlfdirstate(ui, repo)
597 (modified, added, removed, missing, unknown, ignored, clean) = \
597 (modified, added, removed, missing, unknown, ignored, clean) = \
598 lfutil.lfdirstatestatus(lfdirstate, repo, repo['.'].rev())
598 lfutil.lfdirstatestatus(lfdirstate, repo, repo['.'].rev())
599 lfdirstate.write()
599 lfdirstate.write()
600 for lfile in modified:
600 for lfile in modified:
601 lfutil.updatestandin(repo, lfutil.standin(lfile))
601 lfutil.updatestandin(repo, lfutil.standin(lfile))
602 for lfile in missing:
602 for lfile in missing:
603 if (os.path.exists(repo.wjoin(lfutil.standin(lfile)))):
603 if (os.path.exists(repo.wjoin(lfutil.standin(lfile)))):
604 os.unlink(repo.wjoin(lfutil.standin(lfile)))
604 os.unlink(repo.wjoin(lfutil.standin(lfile)))
605
605
606 try:
606 try:
607 ctx = scmutil.revsingle(repo, opts.get('rev'))
607 ctx = scmutil.revsingle(repo, opts.get('rev'))
608 oldmatch = None # for the closure
608 oldmatch = None # for the closure
609 def overridematch(ctx, pats=[], opts={}, globbed=False,
609 def overridematch(ctx, pats=[], opts={}, globbed=False,
610 default='relpath'):
610 default='relpath'):
611 match = oldmatch(ctx, pats, opts, globbed, default)
611 match = oldmatch(ctx, pats, opts, globbed, default)
612 m = copy.copy(match)
612 m = copy.copy(match)
613 def tostandin(f):
613 def tostandin(f):
614 if lfutil.standin(f) in ctx:
614 if lfutil.standin(f) in ctx:
615 return lfutil.standin(f)
615 return lfutil.standin(f)
616 elif lfutil.standin(f) in repo[None]:
616 elif lfutil.standin(f) in repo[None]:
617 return None
617 return None
618 return f
618 return f
619 m._files = [tostandin(f) for f in m._files]
619 m._files = [tostandin(f) for f in m._files]
620 m._files = [f for f in m._files if f is not None]
620 m._files = [f for f in m._files if f is not None]
621 m._fmap = set(m._files)
621 m._fmap = set(m._files)
622 origmatchfn = m.matchfn
622 origmatchfn = m.matchfn
623 def matchfn(f):
623 def matchfn(f):
624 if lfutil.isstandin(f):
624 if lfutil.isstandin(f):
625 # We need to keep track of what largefiles are being
625 # We need to keep track of what largefiles are being
626 # matched so we know which ones to update later --
626 # matched so we know which ones to update later --
627 # otherwise we accidentally revert changes to other
627 # otherwise we accidentally revert changes to other
628 # largefiles. This is repo-specific, so duckpunch the
628 # largefiles. This is repo-specific, so duckpunch the
629 # repo object to keep the list of largefiles for us
629 # repo object to keep the list of largefiles for us
630 # later.
630 # later.
631 if origmatchfn(lfutil.splitstandin(f)) and \
631 if origmatchfn(lfutil.splitstandin(f)) and \
632 (f in repo[None] or f in ctx):
632 (f in repo[None] or f in ctx):
633 lfileslist = getattr(repo, '_lfilestoupdate', [])
633 lfileslist = getattr(repo, '_lfilestoupdate', [])
634 lfileslist.append(lfutil.splitstandin(f))
634 lfileslist.append(lfutil.splitstandin(f))
635 repo._lfilestoupdate = lfileslist
635 repo._lfilestoupdate = lfileslist
636 return True
636 return True
637 else:
637 else:
638 return False
638 return False
639 return origmatchfn(f)
639 return origmatchfn(f)
640 m.matchfn = matchfn
640 m.matchfn = matchfn
641 return m
641 return m
642 oldmatch = installmatchfn(overridematch)
642 oldmatch = installmatchfn(overridematch)
643 scmutil.match
643 scmutil.match
644 matches = overridematch(repo[None], pats, opts)
644 matches = overridematch(repo[None], pats, opts)
645 orig(ui, repo, *pats, **opts)
645 orig(ui, repo, *pats, **opts)
646 finally:
646 finally:
647 restorematchfn()
647 restorematchfn()
648 lfileslist = getattr(repo, '_lfilestoupdate', [])
648 lfileslist = getattr(repo, '_lfilestoupdate', [])
649 lfcommands.updatelfiles(ui, repo, filelist=lfileslist,
649 lfcommands.updatelfiles(ui, repo, filelist=lfileslist,
650 printmessage=False)
650 printmessage=False)
651
651
652 # empty out the largefiles list so we start fresh next time
652 # empty out the largefiles list so we start fresh next time
653 repo._lfilestoupdate = []
653 repo._lfilestoupdate = []
654 for lfile in modified:
654 for lfile in modified:
655 if lfile in lfileslist:
655 if lfile in lfileslist:
656 if os.path.exists(repo.wjoin(lfutil.standin(lfile))) and lfile\
656 if os.path.exists(repo.wjoin(lfutil.standin(lfile))) and lfile\
657 in repo['.']:
657 in repo['.']:
658 lfutil.writestandin(repo, lfutil.standin(lfile),
658 lfutil.writestandin(repo, lfutil.standin(lfile),
659 repo['.'][lfile].data().strip(),
659 repo['.'][lfile].data().strip(),
660 'x' in repo['.'][lfile].flags())
660 'x' in repo['.'][lfile].flags())
661 lfdirstate = lfutil.openlfdirstate(ui, repo)
661 lfdirstate = lfutil.openlfdirstate(ui, repo)
662 for lfile in added:
662 for lfile in added:
663 standin = lfutil.standin(lfile)
663 standin = lfutil.standin(lfile)
664 if standin not in ctx and (standin in matches or opts.get('all')):
664 if standin not in ctx and (standin in matches or opts.get('all')):
665 if lfile in lfdirstate:
665 if lfile in lfdirstate:
666 lfdirstate.drop(lfile)
666 lfdirstate.drop(lfile)
667 util.unlinkpath(repo.wjoin(standin))
667 util.unlinkpath(repo.wjoin(standin))
668 lfdirstate.write()
668 lfdirstate.write()
669 finally:
669 finally:
670 wlock.release()
670 wlock.release()
671
671
672 def hgupdaterepo(orig, repo, node, overwrite):
672 def hgupdaterepo(orig, repo, node, overwrite):
673 if not overwrite:
673 if not overwrite:
674 # Only call updatelfiles on the standins that have changed to save time
674 # Only call updatelfiles on the standins that have changed to save time
675 oldstandins = lfutil.getstandinsstate(repo)
675 oldstandins = lfutil.getstandinsstate(repo)
676
676
677 result = orig(repo, node, overwrite)
677 result = orig(repo, node, overwrite)
678
678
679 filelist = None
679 filelist = None
680 if not overwrite:
680 if not overwrite:
681 newstandins = lfutil.getstandinsstate(repo)
681 newstandins = lfutil.getstandinsstate(repo)
682 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
682 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
683 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist)
683 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist)
684 return result
684 return result
685
685
686 def hgmerge(orig, repo, node, force=None, remind=True):
686 def hgmerge(orig, repo, node, force=None, remind=True):
687 # Mark the repo as being in the middle of a merge, so that
687 # Mark the repo as being in the middle of a merge, so that
688 # updatelfiles() will know that it needs to trust the standins in
688 # updatelfiles() will know that it needs to trust the standins in
689 # the working copy, not in the standins in the current node
689 # the working copy, not in the standins in the current node
690 repo._ismerging = True
690 repo._ismerging = True
691 try:
691 try:
692 result = orig(repo, node, force, remind)
692 result = orig(repo, node, force, remind)
693 lfcommands.updatelfiles(repo.ui, repo)
693 lfcommands.updatelfiles(repo.ui, repo)
694 finally:
694 finally:
695 repo._ismerging = False
695 repo._ismerging = False
696 return result
696 return result
697
697
698 # When we rebase a repository with remotely changed largefiles, we need to
698 # When we rebase a repository with remotely changed largefiles, we need to
699 # take some extra care so that the largefiles are correctly updated in the
699 # take some extra care so that the largefiles are correctly updated in the
700 # working copy
700 # working copy
701 def overridepull(orig, ui, repo, source=None, **opts):
701 def overridepull(orig, ui, repo, source=None, **opts):
702 revsprepull = len(repo)
702 revsprepull = len(repo)
703 if opts.get('rebase', False):
703 if opts.get('rebase', False):
704 repo._isrebasing = True
704 repo._isrebasing = True
705 try:
705 try:
706 if opts.get('update'):
706 if opts.get('update'):
707 del opts['update']
707 del opts['update']
708 ui.debug('--update and --rebase are not compatible, ignoring '
708 ui.debug('--update and --rebase are not compatible, ignoring '
709 'the update flag\n')
709 'the update flag\n')
710 del opts['rebase']
710 del opts['rebase']
711 cmdutil.bailifchanged(repo)
711 cmdutil.bailifchanged(repo)
712 origpostincoming = commands.postincoming
712 origpostincoming = commands.postincoming
713 def _dummy(*args, **kwargs):
713 def _dummy(*args, **kwargs):
714 pass
714 pass
715 commands.postincoming = _dummy
715 commands.postincoming = _dummy
716 if not source:
716 if not source:
717 source = 'default'
717 source = 'default'
718 repo.lfpullsource = source
718 repo.lfpullsource = source
719 try:
719 try:
720 result = commands.pull(ui, repo, source, **opts)
720 result = commands.pull(ui, repo, source, **opts)
721 finally:
721 finally:
722 commands.postincoming = origpostincoming
722 commands.postincoming = origpostincoming
723 revspostpull = len(repo)
723 revspostpull = len(repo)
724 if revspostpull > revsprepull:
724 if revspostpull > revsprepull:
725 result = result or rebase.rebase(ui, repo)
725 result = result or rebase.rebase(ui, repo)
726 finally:
726 finally:
727 repo._isrebasing = False
727 repo._isrebasing = False
728 else:
728 else:
729 if not source:
729 if not source:
730 source = 'default'
730 source = 'default'
731 repo.lfpullsource = source
731 repo.lfpullsource = source
732 oldheads = lfutil.getcurrentheads(repo)
732 oldheads = lfutil.getcurrentheads(repo)
733 result = orig(ui, repo, source, **opts)
733 result = orig(ui, repo, source, **opts)
734 # If we do not have the new largefiles for any new heads we pulled, we
734 # If we do not have the new largefiles for any new heads we pulled, we
735 # will run into a problem later if we try to merge or rebase with one of
735 # will run into a problem later if we try to merge or rebase with one of
736 # these heads, so cache the largefiles now directly into the system
736 # these heads, so cache the largefiles now directly into the system
737 # cache.
737 # cache.
738 ui.status(_("caching new largefiles\n"))
738 ui.status(_("caching new largefiles\n"))
739 numcached = 0
739 numcached = 0
740 heads = lfutil.getcurrentheads(repo)
740 heads = lfutil.getcurrentheads(repo)
741 newheads = set(heads).difference(set(oldheads))
741 newheads = set(heads).difference(set(oldheads))
742 for head in newheads:
742 for head in newheads:
743 (cached, missing) = lfcommands.cachelfiles(ui, repo, head)
743 (cached, missing) = lfcommands.cachelfiles(ui, repo, head)
744 numcached += len(cached)
744 numcached += len(cached)
745 ui.status(_("%d largefiles cached\n") % numcached)
745 ui.status(_("%d largefiles cached\n") % numcached)
746 if opts.get('all_largefiles'):
746 if opts.get('all_largefiles'):
747 revspostpull = len(repo)
747 revspostpull = len(repo)
748 revs = []
748 revs = []
749 for rev in xrange(revsprepull + 1, revspostpull):
749 for rev in xrange(revsprepull + 1, revspostpull):
750 revs.append(repo[rev].rev())
750 revs.append(repo[rev].rev())
751 lfcommands.downloadlfiles(ui, repo, revs)
751 lfcommands.downloadlfiles(ui, repo, revs)
752 return result
752 return result
753
753
754 def overrideclone(orig, ui, source, dest=None, **opts):
754 def overrideclone(orig, ui, source, dest=None, **opts):
755 d = dest
755 d = dest
756 if d is None:
756 if d is None:
757 d = hg.defaultdest(source)
757 d = hg.defaultdest(source)
758 if opts.get('all_largefiles') and not hg.islocal(d):
758 if opts.get('all_largefiles') and not hg.islocal(d):
759 raise util.Abort(_(
759 raise util.Abort(_(
760 '--all-largefiles is incompatible with non-local destination %s' %
760 '--all-largefiles is incompatible with non-local destination %s' %
761 d))
761 d))
762
762
763 return orig(ui, source, dest, **opts)
763 return orig(ui, source, dest, **opts)
764
764
765 def hgclone(orig, ui, opts, *args, **kwargs):
765 def hgclone(orig, ui, opts, *args, **kwargs):
766 result = orig(ui, opts, *args, **kwargs)
766 result = orig(ui, opts, *args, **kwargs)
767
767
768 if result is not None:
768 if result is not None:
769 sourcerepo, destrepo = result
769 sourcerepo, destrepo = result
770 repo = destrepo.local()
770 repo = destrepo.local()
771
771
772 # The .hglf directory must exist for the standin matcher to match
772 # The .hglf directory must exist for the standin matcher to match
773 # anything (which listlfiles uses for each rev), and .hg/largefiles is
773 # anything (which listlfiles uses for each rev), and .hg/largefiles is
774 # assumed to exist by the code that caches the downloaded file. These
774 # assumed to exist by the code that caches the downloaded file. These
775 # directories exist if clone updated to any rev. (If the repo does not
775 # directories exist if clone updated to any rev. (If the repo does not
776 # have largefiles, download never gets to the point of needing
776 # have largefiles, download never gets to the point of needing
777 # .hg/largefiles, and the standin matcher won't match anything anyway.)
777 # .hg/largefiles, and the standin matcher won't match anything anyway.)
778 if 'largefiles' in repo.requirements:
778 if 'largefiles' in repo.requirements:
779 if opts.get('noupdate'):
779 if opts.get('noupdate'):
780 util.makedirs(repo.wjoin(lfutil.shortname))
780 util.makedirs(repo.wjoin(lfutil.shortname))
781 util.makedirs(repo.join(lfutil.longname))
781 util.makedirs(repo.join(lfutil.longname))
782
782
783 # Caching is implicitly limited to 'rev' option, since the dest repo was
783 # Caching is implicitly limited to 'rev' option, since the dest repo was
784 # truncated at that point. The user may expect a download count with
784 # truncated at that point. The user may expect a download count with
785 # this option, so attempt whether or not this is a largefile repo.
785 # this option, so attempt whether or not this is a largefile repo.
786 if opts.get('all_largefiles'):
786 if opts.get('all_largefiles'):
787 success, missing = lfcommands.downloadlfiles(ui, repo, None)
787 success, missing = lfcommands.downloadlfiles(ui, repo, None)
788
788
789 if missing != 0:
789 if missing != 0:
790 return None
790 return None
791
791
792 return result
792 return result
793
793
794 def overriderebase(orig, ui, repo, **opts):
794 def overriderebase(orig, ui, repo, **opts):
795 repo._isrebasing = True
795 repo._isrebasing = True
796 try:
796 try:
797 return orig(ui, repo, **opts)
797 return orig(ui, repo, **opts)
798 finally:
798 finally:
799 repo._isrebasing = False
799 repo._isrebasing = False
800
800
801 def overridearchive(orig, repo, dest, node, kind, decode=True, matchfn=None,
801 def overridearchive(orig, repo, dest, node, kind, decode=True, matchfn=None,
802 prefix=None, mtime=None, subrepos=None):
802 prefix=None, mtime=None, subrepos=None):
803 # No need to lock because we are only reading history and
803 # No need to lock because we are only reading history and
804 # largefile caches, neither of which are modified.
804 # largefile caches, neither of which are modified.
805 lfcommands.cachelfiles(repo.ui, repo, node)
805 lfcommands.cachelfiles(repo.ui, repo, node)
806
806
807 if kind not in archival.archivers:
807 if kind not in archival.archivers:
808 raise util.Abort(_("unknown archive type '%s'") % kind)
808 raise util.Abort(_("unknown archive type '%s'") % kind)
809
809
810 ctx = repo[node]
810 ctx = repo[node]
811
811
812 if kind == 'files':
812 if kind == 'files':
813 if prefix:
813 if prefix:
814 raise util.Abort(
814 raise util.Abort(
815 _('cannot give prefix when archiving to files'))
815 _('cannot give prefix when archiving to files'))
816 else:
816 else:
817 prefix = archival.tidyprefix(dest, kind, prefix)
817 prefix = archival.tidyprefix(dest, kind, prefix)
818
818
819 def write(name, mode, islink, getdata):
819 def write(name, mode, islink, getdata):
820 if matchfn and not matchfn(name):
820 if matchfn and not matchfn(name):
821 return
821 return
822 data = getdata()
822 data = getdata()
823 if decode:
823 if decode:
824 data = repo.wwritedata(name, data)
824 data = repo.wwritedata(name, data)
825 archiver.addfile(prefix + name, mode, islink, data)
825 archiver.addfile(prefix + name, mode, islink, data)
826
826
827 archiver = archival.archivers[kind](dest, mtime or ctx.date()[0])
827 archiver = archival.archivers[kind](dest, mtime or ctx.date()[0])
828
828
829 if repo.ui.configbool("ui", "archivemeta", True):
829 if repo.ui.configbool("ui", "archivemeta", True):
830 def metadata():
830 def metadata():
831 base = 'repo: %s\nnode: %s\nbranch: %s\n' % (
831 base = 'repo: %s\nnode: %s\nbranch: %s\n' % (
832 hex(repo.changelog.node(0)), hex(node), ctx.branch())
832 hex(repo.changelog.node(0)), hex(node), ctx.branch())
833
833
834 tags = ''.join('tag: %s\n' % t for t in ctx.tags()
834 tags = ''.join('tag: %s\n' % t for t in ctx.tags()
835 if repo.tagtype(t) == 'global')
835 if repo.tagtype(t) == 'global')
836 if not tags:
836 if not tags:
837 repo.ui.pushbuffer()
837 repo.ui.pushbuffer()
838 opts = {'template': '{latesttag}\n{latesttagdistance}',
838 opts = {'template': '{latesttag}\n{latesttagdistance}',
839 'style': '', 'patch': None, 'git': None}
839 'style': '', 'patch': None, 'git': None}
840 cmdutil.show_changeset(repo.ui, repo, opts).show(ctx)
840 cmdutil.show_changeset(repo.ui, repo, opts).show(ctx)
841 ltags, dist = repo.ui.popbuffer().split('\n')
841 ltags, dist = repo.ui.popbuffer().split('\n')
842 tags = ''.join('latesttag: %s\n' % t for t in ltags.split(':'))
842 tags = ''.join('latesttag: %s\n' % t for t in ltags.split(':'))
843 tags += 'latesttagdistance: %s\n' % dist
843 tags += 'latesttagdistance: %s\n' % dist
844
844
845 return base + tags
845 return base + tags
846
846
847 write('.hg_archival.txt', 0644, False, metadata)
847 write('.hg_archival.txt', 0644, False, metadata)
848
848
849 for f in ctx:
849 for f in ctx:
850 ff = ctx.flags(f)
850 ff = ctx.flags(f)
851 getdata = ctx[f].data
851 getdata = ctx[f].data
852 if lfutil.isstandin(f):
852 if lfutil.isstandin(f):
853 path = lfutil.findfile(repo, getdata().strip())
853 path = lfutil.findfile(repo, getdata().strip())
854 if path is None:
854 if path is None:
855 raise util.Abort(
855 raise util.Abort(
856 _('largefile %s not found in repo store or system cache')
856 _('largefile %s not found in repo store or system cache')
857 % lfutil.splitstandin(f))
857 % lfutil.splitstandin(f))
858 f = lfutil.splitstandin(f)
858 f = lfutil.splitstandin(f)
859
859
860 def getdatafn():
860 def getdatafn():
861 fd = None
861 fd = None
862 try:
862 try:
863 fd = open(path, 'rb')
863 fd = open(path, 'rb')
864 return fd.read()
864 return fd.read()
865 finally:
865 finally:
866 if fd:
866 if fd:
867 fd.close()
867 fd.close()
868
868
869 getdata = getdatafn
869 getdata = getdatafn
870 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
870 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
871
871
872 if subrepos:
872 if subrepos:
873 for subpath in sorted(ctx.substate):
873 for subpath in sorted(ctx.substate):
874 sub = ctx.sub(subpath)
874 sub = ctx.sub(subpath)
875 submatch = match_.narrowmatcher(subpath, matchfn)
875 submatch = match_.narrowmatcher(subpath, matchfn)
876 sub.archive(repo.ui, archiver, prefix, submatch)
876 sub.archive(repo.ui, archiver, prefix, submatch)
877
877
878 archiver.done()
878 archiver.done()
879
879
880 def hgsubrepoarchive(orig, repo, ui, archiver, prefix, match=None):
880 def hgsubrepoarchive(orig, repo, ui, archiver, prefix, match=None):
881 repo._get(repo._state + ('hg',))
881 repo._get(repo._state + ('hg',))
882 rev = repo._state[1]
882 rev = repo._state[1]
883 ctx = repo._repo[rev]
883 ctx = repo._repo[rev]
884
884
885 lfcommands.cachelfiles(ui, repo._repo, ctx.node())
885 lfcommands.cachelfiles(ui, repo._repo, ctx.node())
886
886
887 def write(name, mode, islink, getdata):
887 def write(name, mode, islink, getdata):
888 # At this point, the standin has been replaced with the largefile name,
888 # At this point, the standin has been replaced with the largefile name,
889 # so the normal matcher works here without the lfutil variants.
889 # so the normal matcher works here without the lfutil variants.
890 if match and not match(f):
890 if match and not match(f):
891 return
891 return
892 data = getdata()
892 data = getdata()
893
893
894 archiver.addfile(prefix + repo._path + '/' + name, mode, islink, data)
894 archiver.addfile(prefix + repo._path + '/' + name, mode, islink, data)
895
895
896 for f in ctx:
896 for f in ctx:
897 ff = ctx.flags(f)
897 ff = ctx.flags(f)
898 getdata = ctx[f].data
898 getdata = ctx[f].data
899 if lfutil.isstandin(f):
899 if lfutil.isstandin(f):
900 path = lfutil.findfile(repo._repo, getdata().strip())
900 path = lfutil.findfile(repo._repo, getdata().strip())
901 if path is None:
901 if path is None:
902 raise util.Abort(
902 raise util.Abort(
903 _('largefile %s not found in repo store or system cache')
903 _('largefile %s not found in repo store or system cache')
904 % lfutil.splitstandin(f))
904 % lfutil.splitstandin(f))
905 f = lfutil.splitstandin(f)
905 f = lfutil.splitstandin(f)
906
906
907 def getdatafn():
907 def getdatafn():
908 fd = None
908 fd = None
909 try:
909 try:
910 fd = open(os.path.join(prefix, path), 'rb')
910 fd = open(os.path.join(prefix, path), 'rb')
911 return fd.read()
911 return fd.read()
912 finally:
912 finally:
913 if fd:
913 if fd:
914 fd.close()
914 fd.close()
915
915
916 getdata = getdatafn
916 getdata = getdatafn
917
917
918 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
918 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
919
919
920 for subpath in sorted(ctx.substate):
920 for subpath in sorted(ctx.substate):
921 sub = ctx.sub(subpath)
921 sub = ctx.sub(subpath)
922 submatch = match_.narrowmatcher(subpath, match)
922 submatch = match_.narrowmatcher(subpath, match)
923 sub.archive(ui, archiver, os.path.join(prefix, repo._path) + '/',
923 sub.archive(ui, archiver, os.path.join(prefix, repo._path) + '/',
924 submatch)
924 submatch)
925
925
926 # If a largefile is modified, the change is not reflected in its
926 # If a largefile is modified, the change is not reflected in its
927 # standin until a commit. cmdutil.bailifchanged() raises an exception
927 # standin until a commit. cmdutil.bailifchanged() raises an exception
928 # if the repo has uncommitted changes. Wrap it to also check if
928 # if the repo has uncommitted changes. Wrap it to also check if
929 # largefiles were changed. This is used by bisect and backout.
929 # largefiles were changed. This is used by bisect and backout.
930 def overridebailifchanged(orig, repo):
930 def overridebailifchanged(orig, repo):
931 orig(repo)
931 orig(repo)
932 repo.lfstatus = True
932 repo.lfstatus = True
933 modified, added, removed, deleted = repo.status()[:4]
933 modified, added, removed, deleted = repo.status()[:4]
934 repo.lfstatus = False
934 repo.lfstatus = False
935 if modified or added or removed or deleted:
935 if modified or added or removed or deleted:
936 raise util.Abort(_('outstanding uncommitted changes'))
936 raise util.Abort(_('outstanding uncommitted changes'))
937
937
938 # Fetch doesn't use cmdutil.bailifchanged so override it to add the check
938 # Fetch doesn't use cmdutil.bailifchanged so override it to add the check
939 def overridefetch(orig, ui, repo, *pats, **opts):
939 def overridefetch(orig, ui, repo, *pats, **opts):
940 repo.lfstatus = True
940 repo.lfstatus = True
941 modified, added, removed, deleted = repo.status()[:4]
941 modified, added, removed, deleted = repo.status()[:4]
942 repo.lfstatus = False
942 repo.lfstatus = False
943 if modified or added or removed or deleted:
943 if modified or added or removed or deleted:
944 raise util.Abort(_('outstanding uncommitted changes'))
944 raise util.Abort(_('outstanding uncommitted changes'))
945 return orig(ui, repo, *pats, **opts)
945 return orig(ui, repo, *pats, **opts)
946
946
947 def overrideforget(orig, ui, repo, *pats, **opts):
947 def overrideforget(orig, ui, repo, *pats, **opts):
948 installnormalfilesmatchfn(repo[None].manifest())
948 installnormalfilesmatchfn(repo[None].manifest())
949 result = orig(ui, repo, *pats, **opts)
949 result = orig(ui, repo, *pats, **opts)
950 restorematchfn()
950 restorematchfn()
951 m = scmutil.match(repo[None], pats, opts)
951 m = scmutil.match(repo[None], pats, opts)
952
952
953 try:
953 try:
954 repo.lfstatus = True
954 repo.lfstatus = True
955 s = repo.status(match=m, clean=True)
955 s = repo.status(match=m, clean=True)
956 finally:
956 finally:
957 repo.lfstatus = False
957 repo.lfstatus = False
958 forget = sorted(s[0] + s[1] + s[3] + s[6])
958 forget = sorted(s[0] + s[1] + s[3] + s[6])
959 forget = [f for f in forget if lfutil.standin(f) in repo[None].manifest()]
959 forget = [f for f in forget if lfutil.standin(f) in repo[None].manifest()]
960
960
961 for f in forget:
961 for f in forget:
962 if lfutil.standin(f) not in repo.dirstate and not \
962 if lfutil.standin(f) not in repo.dirstate and not \
963 os.path.isdir(m.rel(lfutil.standin(f))):
963 os.path.isdir(m.rel(lfutil.standin(f))):
964 ui.warn(_('not removing %s: file is already untracked\n')
964 ui.warn(_('not removing %s: file is already untracked\n')
965 % m.rel(f))
965 % m.rel(f))
966 result = 1
966 result = 1
967
967
968 for f in forget:
968 for f in forget:
969 if ui.verbose or not m.exact(f):
969 if ui.verbose or not m.exact(f):
970 ui.status(_('removing %s\n') % m.rel(f))
970 ui.status(_('removing %s\n') % m.rel(f))
971
971
972 # Need to lock because standin files are deleted then removed from the
972 # Need to lock because standin files are deleted then removed from the
973 # repository and we could race in-between.
973 # repository and we could race in-between.
974 wlock = repo.wlock()
974 wlock = repo.wlock()
975 try:
975 try:
976 lfdirstate = lfutil.openlfdirstate(ui, repo)
976 lfdirstate = lfutil.openlfdirstate(ui, repo)
977 for f in forget:
977 for f in forget:
978 if lfdirstate[f] == 'a':
978 if lfdirstate[f] == 'a':
979 lfdirstate.drop(f)
979 lfdirstate.drop(f)
980 else:
980 else:
981 lfdirstate.remove(f)
981 lfdirstate.remove(f)
982 lfdirstate.write()
982 lfdirstate.write()
983 standins = [lfutil.standin(f) for f in forget]
983 standins = [lfutil.standin(f) for f in forget]
984 for f in standins:
984 for f in standins:
985 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
985 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
986 repo[None].forget(standins)
986 repo[None].forget(standins)
987 finally:
987 finally:
988 wlock.release()
988 wlock.release()
989
989
990 return result
990 return result
991
991
992 def getoutgoinglfiles(ui, repo, dest=None, **opts):
992 def getoutgoinglfiles(ui, repo, dest=None, **opts):
993 dest = ui.expandpath(dest or 'default-push', dest or 'default')
993 dest = ui.expandpath(dest or 'default-push', dest or 'default')
994 dest, branches = hg.parseurl(dest, opts.get('branch'))
994 dest, branches = hg.parseurl(dest, opts.get('branch'))
995 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
995 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
996 if revs:
996 if revs:
997 revs = [repo.lookup(rev) for rev in scmutil.revrange(repo, revs)]
997 revs = [repo.lookup(rev) for rev in scmutil.revrange(repo, revs)]
998
998
999 try:
999 try:
1000 remote = hg.peer(repo, opts, dest)
1000 remote = hg.peer(repo, opts, dest)
1001 except error.RepoError:
1001 except error.RepoError:
1002 return None
1002 return None
1003 outgoing = discovery.findcommonoutgoing(repo, remote.peer(), force=False)
1003 outgoing = discovery.findcommonoutgoing(repo, remote.peer(), force=False)
1004 if not outgoing.missing:
1004 if not outgoing.missing:
1005 return outgoing.missing
1005 return outgoing.missing
1006 o = repo.changelog.nodesbetween(outgoing.missing, revs)[0]
1006 o = repo.changelog.nodesbetween(outgoing.missing, revs)[0]
1007 if opts.get('newest_first'):
1007 if opts.get('newest_first'):
1008 o.reverse()
1008 o.reverse()
1009
1009
1010 toupload = set()
1010 toupload = set()
1011 for n in o:
1011 for n in o:
1012 parents = [p for p in repo.changelog.parents(n) if p != node.nullid]
1012 parents = [p for p in repo.changelog.parents(n) if p != node.nullid]
1013 ctx = repo[n]
1013 ctx = repo[n]
1014 files = set(ctx.files())
1014 files = set(ctx.files())
1015 if len(parents) == 2:
1015 if len(parents) == 2:
1016 mc = ctx.manifest()
1016 mc = ctx.manifest()
1017 mp1 = ctx.parents()[0].manifest()
1017 mp1 = ctx.parents()[0].manifest()
1018 mp2 = ctx.parents()[1].manifest()
1018 mp2 = ctx.parents()[1].manifest()
1019 for f in mp1:
1019 for f in mp1:
1020 if f not in mc:
1020 if f not in mc:
1021 files.add(f)
1021 files.add(f)
1022 for f in mp2:
1022 for f in mp2:
1023 if f not in mc:
1023 if f not in mc:
1024 files.add(f)
1024 files.add(f)
1025 for f in mc:
1025 for f in mc:
1026 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
1026 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
1027 files.add(f)
1027 files.add(f)
1028 toupload = toupload.union(
1028 toupload = toupload.union(
1029 set([f for f in files if lfutil.isstandin(f) and f in ctx]))
1029 set([f for f in files if lfutil.isstandin(f) and f in ctx]))
1030 return sorted(toupload)
1030 return sorted(toupload)
1031
1031
1032 def overrideoutgoing(orig, ui, repo, dest=None, **opts):
1032 def overrideoutgoing(orig, ui, repo, dest=None, **opts):
1033 result = orig(ui, repo, dest, **opts)
1033 result = orig(ui, repo, dest, **opts)
1034
1034
1035 if opts.pop('large', None):
1035 if opts.pop('large', None):
1036 toupload = getoutgoinglfiles(ui, repo, dest, **opts)
1036 toupload = getoutgoinglfiles(ui, repo, dest, **opts)
1037 if toupload is None:
1037 if toupload is None:
1038 ui.status(_('largefiles: No remote repo\n'))
1038 ui.status(_('largefiles: No remote repo\n'))
1039 elif not toupload:
1039 elif not toupload:
1040 ui.status(_('largefiles: no files to upload\n'))
1040 ui.status(_('largefiles: no files to upload\n'))
1041 else:
1041 else:
1042 ui.status(_('largefiles to upload:\n'))
1042 ui.status(_('largefiles to upload:\n'))
1043 for file in toupload:
1043 for file in toupload:
1044 ui.status(lfutil.splitstandin(file) + '\n')
1044 ui.status(lfutil.splitstandin(file) + '\n')
1045 ui.status('\n')
1045 ui.status('\n')
1046
1046
1047 return result
1047 return result
1048
1048
1049 def overridesummary(orig, ui, repo, *pats, **opts):
1049 def overridesummary(orig, ui, repo, *pats, **opts):
1050 try:
1050 try:
1051 repo.lfstatus = True
1051 repo.lfstatus = True
1052 orig(ui, repo, *pats, **opts)
1052 orig(ui, repo, *pats, **opts)
1053 finally:
1053 finally:
1054 repo.lfstatus = False
1054 repo.lfstatus = False
1055
1055
1056 if opts.pop('large', None):
1056 if opts.pop('large', None):
1057 toupload = getoutgoinglfiles(ui, repo, None, **opts)
1057 toupload = getoutgoinglfiles(ui, repo, None, **opts)
1058 if toupload is None:
1058 if toupload is None:
1059 # i18n: column positioning for "hg summary"
1059 # i18n: column positioning for "hg summary"
1060 ui.status(_('largefiles: (no remote repo)\n'))
1060 ui.status(_('largefiles: (no remote repo)\n'))
1061 elif not toupload:
1061 elif not toupload:
1062 # i18n: column positioning for "hg summary"
1062 # i18n: column positioning for "hg summary"
1063 ui.status(_('largefiles: (no files to upload)\n'))
1063 ui.status(_('largefiles: (no files to upload)\n'))
1064 else:
1064 else:
1065 # i18n: column positioning for "hg summary"
1065 # i18n: column positioning for "hg summary"
1066 ui.status(_('largefiles: %d to upload\n') % len(toupload))
1066 ui.status(_('largefiles: %d to upload\n') % len(toupload))
1067
1067
1068 def scmutiladdremove(orig, repo, pats=[], opts={}, dry_run=None,
1068 def scmutiladdremove(orig, repo, pats=[], opts={}, dry_run=None,
1069 similarity=None):
1069 similarity=None):
1070 if not lfutil.islfilesrepo(repo):
1070 if not lfutil.islfilesrepo(repo):
1071 return orig(repo, pats, opts, dry_run, similarity)
1071 return orig(repo, pats, opts, dry_run, similarity)
1072 # Get the list of missing largefiles so we can remove them
1072 # Get the list of missing largefiles so we can remove them
1073 lfdirstate = lfutil.openlfdirstate(repo.ui, repo)
1073 lfdirstate = lfutil.openlfdirstate(repo.ui, repo)
1074 s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
1074 s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
1075 False, False)
1075 False, False)
1076 (unsure, modified, added, removed, missing, unknown, ignored, clean) = s
1076 (unsure, modified, added, removed, missing, unknown, ignored, clean) = s
1077
1077
1078 # Call into the normal remove code, but the removing of the standin, we want
1078 # Call into the normal remove code, but the removing of the standin, we want
1079 # to have handled by original addremove. Monkey patching here makes sure
1079 # to have handled by original addremove. Monkey patching here makes sure
1080 # we don't remove the standin in the largefiles code, preventing a very
1080 # we don't remove the standin in the largefiles code, preventing a very
1081 # confused state later.
1081 # confused state later.
1082 if missing:
1082 if missing:
1083 m = [repo.wjoin(f) for f in missing]
1083 m = [repo.wjoin(f) for f in missing]
1084 repo._isaddremove = True
1084 repo._isaddremove = True
1085 removelargefiles(repo.ui, repo, *m, **opts)
1085 removelargefiles(repo.ui, repo, *m, **opts)
1086 repo._isaddremove = False
1086 repo._isaddremove = False
1087 # Call into the normal add code, and any files that *should* be added as
1087 # Call into the normal add code, and any files that *should* be added as
1088 # largefiles will be
1088 # largefiles will be
1089 addlargefiles(repo.ui, repo, *pats, **opts)
1089 addlargefiles(repo.ui, repo, *pats, **opts)
1090 # Now that we've handled largefiles, hand off to the original addremove
1090 # Now that we've handled largefiles, hand off to the original addremove
1091 # function to take care of the rest. Make sure it doesn't do anything with
1091 # function to take care of the rest. Make sure it doesn't do anything with
1092 # largefiles by installing a matcher that will ignore them.
1092 # largefiles by installing a matcher that will ignore them.
1093 installnormalfilesmatchfn(repo[None].manifest())
1093 installnormalfilesmatchfn(repo[None].manifest())
1094 result = orig(repo, pats, opts, dry_run, similarity)
1094 result = orig(repo, pats, opts, dry_run, similarity)
1095 restorematchfn()
1095 restorematchfn()
1096 return result
1096 return result
1097
1097
1098 # Calling purge with --all will cause the largefiles to be deleted.
1098 # Calling purge with --all will cause the largefiles to be deleted.
1099 # Override repo.status to prevent this from happening.
1099 # Override repo.status to prevent this from happening.
1100 def overridepurge(orig, ui, repo, *dirs, **opts):
1100 def overridepurge(orig, ui, repo, *dirs, **opts):
1101 # XXX large file status is buggy when used on repo proxy.
1101 # XXX large file status is buggy when used on repo proxy.
1102 # XXX this needs to be investigate.
1102 # XXX this needs to be investigate.
1103 repo = repo.unfiltered()
1103 repo = repo.unfiltered()
1104 oldstatus = repo.status
1104 oldstatus = repo.status
1105 def overridestatus(node1='.', node2=None, match=None, ignored=False,
1105 def overridestatus(node1='.', node2=None, match=None, ignored=False,
1106 clean=False, unknown=False, listsubrepos=False):
1106 clean=False, unknown=False, listsubrepos=False):
1107 r = oldstatus(node1, node2, match, ignored, clean, unknown,
1107 r = oldstatus(node1, node2, match, ignored, clean, unknown,
1108 listsubrepos)
1108 listsubrepos)
1109 lfdirstate = lfutil.openlfdirstate(ui, repo)
1109 lfdirstate = lfutil.openlfdirstate(ui, repo)
1110 modified, added, removed, deleted, unknown, ignored, clean = r
1110 modified, added, removed, deleted, unknown, ignored, clean = r
1111 unknown = [f for f in unknown if lfdirstate[f] == '?']
1111 unknown = [f for f in unknown if lfdirstate[f] == '?']
1112 ignored = [f for f in ignored if lfdirstate[f] == '?']
1112 ignored = [f for f in ignored if lfdirstate[f] == '?']
1113 return modified, added, removed, deleted, unknown, ignored, clean
1113 return modified, added, removed, deleted, unknown, ignored, clean
1114 repo.status = overridestatus
1114 repo.status = overridestatus
1115 orig(ui, repo, *dirs, **opts)
1115 orig(ui, repo, *dirs, **opts)
1116 repo.status = oldstatus
1116 repo.status = oldstatus
1117
1117
1118 def overriderollback(orig, ui, repo, **opts):
1118 def overriderollback(orig, ui, repo, **opts):
1119 result = orig(ui, repo, **opts)
1119 result = orig(ui, repo, **opts)
1120 merge.update(repo, node=None, branchmerge=False, force=True,
1120 merge.update(repo, node=None, branchmerge=False, force=True,
1121 partial=lfutil.isstandin)
1121 partial=lfutil.isstandin)
1122 wlock = repo.wlock()
1122 wlock = repo.wlock()
1123 try:
1123 try:
1124 lfdirstate = lfutil.openlfdirstate(ui, repo)
1124 lfdirstate = lfutil.openlfdirstate(ui, repo)
1125 lfiles = lfutil.listlfiles(repo)
1125 lfiles = lfutil.listlfiles(repo)
1126 oldlfiles = lfutil.listlfiles(repo, repo[None].parents()[0].rev())
1126 oldlfiles = lfutil.listlfiles(repo, repo[None].parents()[0].rev())
1127 for file in lfiles:
1127 for file in lfiles:
1128 if file in oldlfiles:
1128 if file in oldlfiles:
1129 lfdirstate.normallookup(file)
1129 lfdirstate.normallookup(file)
1130 else:
1130 else:
1131 lfdirstate.add(file)
1131 lfdirstate.add(file)
1132 lfdirstate.write()
1132 lfdirstate.write()
1133 finally:
1133 finally:
1134 wlock.release()
1134 wlock.release()
1135 return result
1135 return result
1136
1136
1137 def overridetransplant(orig, ui, repo, *revs, **opts):
1137 def overridetransplant(orig, ui, repo, *revs, **opts):
1138 try:
1138 try:
1139 oldstandins = lfutil.getstandinsstate(repo)
1139 oldstandins = lfutil.getstandinsstate(repo)
1140 repo._istransplanting = True
1140 repo._istransplanting = True
1141 result = orig(ui, repo, *revs, **opts)
1141 result = orig(ui, repo, *revs, **opts)
1142 newstandins = lfutil.getstandinsstate(repo)
1142 newstandins = lfutil.getstandinsstate(repo)
1143 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
1143 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
1144 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist,
1144 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist,
1145 printmessage=True)
1145 printmessage=True)
1146 finally:
1146 finally:
1147 repo._istransplanting = False
1147 repo._istransplanting = False
1148 return result
1148 return result
1149
1149
1150 def overridecat(orig, ui, repo, file1, *pats, **opts):
1150 def overridecat(orig, ui, repo, file1, *pats, **opts):
1151 ctx = scmutil.revsingle(repo, opts.get('rev'))
1151 ctx = scmutil.revsingle(repo, opts.get('rev'))
1152 err = 1
1152 err = 1
1153 notbad = set()
1153 notbad = set()
1154 m = scmutil.match(ctx, (file1,) + pats, opts)
1154 m = scmutil.match(ctx, (file1,) + pats, opts)
1155 origmatchfn = m.matchfn
1155 origmatchfn = m.matchfn
1156 def lfmatchfn(f):
1156 def lfmatchfn(f):
1157 lf = lfutil.splitstandin(f)
1157 lf = lfutil.splitstandin(f)
1158 if lf is None:
1158 if lf is None:
1159 return origmatchfn(f)
1159 return origmatchfn(f)
1160 notbad.add(lf)
1160 notbad.add(lf)
1161 return origmatchfn(lf)
1161 return origmatchfn(lf)
1162 m.matchfn = lfmatchfn
1162 m.matchfn = lfmatchfn
1163 m.bad = lambda f, msg: f not in notbad
1163 m.bad = lambda f, msg: f not in notbad
1164 for f in ctx.walk(m):
1164 for f in ctx.walk(m):
1165 lf = lfutil.splitstandin(f)
1165 lf = lfutil.splitstandin(f)
1166 if lf is None:
1166 if lf is None:
1167 err = orig(ui, repo, f, **opts)
1167 err = orig(ui, repo, f, **opts)
1168 else:
1168 else:
1169 err = lfcommands.catlfile(repo, lf, ctx.rev(), opts.get('output'))
1169 err = lfcommands.catlfile(repo, lf, ctx.rev(), opts.get('output'))
1170 return err
1170 return err
1171
1171
1172 def mercurialsinkbefore(orig, sink):
1172 def mercurialsinkbefore(orig, sink):
1173 sink.repo._isconverting = True
1173 sink.repo._isconverting = True
1174 orig(sink)
1174 orig(sink)
1175
1175
1176 def mercurialsinkafter(orig, sink):
1176 def mercurialsinkafter(orig, sink):
1177 sink.repo._isconverting = False
1177 sink.repo._isconverting = False
1178 orig(sink)
1178 orig(sink)
@@ -1,649 +1,649 b''
1 # merge.py - directory-level update/merge handling for Mercurial
1 # merge.py - directory-level update/merge handling for Mercurial
2 #
2 #
3 # Copyright 2006, 2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2006, 2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import nullid, nullrev, hex, bin
8 from node import nullid, nullrev, hex, bin
9 from i18n import _
9 from i18n import _
10 import error, util, filemerge, copies, subrepo
10 import error, util, filemerge, copies, subrepo
11 import errno, os, shutil
11 import errno, os, shutil
12
12
13 class mergestate(object):
13 class mergestate(object):
14 '''track 3-way merge state of individual files'''
14 '''track 3-way merge state of individual files'''
15 def __init__(self, repo):
15 def __init__(self, repo):
16 self._repo = repo
16 self._repo = repo
17 self._dirty = False
17 self._dirty = False
18 self._read()
18 self._read()
19 def reset(self, node=None):
19 def reset(self, node=None):
20 self._state = {}
20 self._state = {}
21 if node:
21 if node:
22 self._local = node
22 self._local = node
23 shutil.rmtree(self._repo.join("merge"), True)
23 shutil.rmtree(self._repo.join("merge"), True)
24 self._dirty = False
24 self._dirty = False
25 def _read(self):
25 def _read(self):
26 self._state = {}
26 self._state = {}
27 try:
27 try:
28 f = self._repo.opener("merge/state")
28 f = self._repo.opener("merge/state")
29 for i, l in enumerate(f):
29 for i, l in enumerate(f):
30 if i == 0:
30 if i == 0:
31 self._local = bin(l[:-1])
31 self._local = bin(l[:-1])
32 else:
32 else:
33 bits = l[:-1].split("\0")
33 bits = l[:-1].split("\0")
34 self._state[bits[0]] = bits[1:]
34 self._state[bits[0]] = bits[1:]
35 f.close()
35 f.close()
36 except IOError, err:
36 except IOError, err:
37 if err.errno != errno.ENOENT:
37 if err.errno != errno.ENOENT:
38 raise
38 raise
39 self._dirty = False
39 self._dirty = False
40 def commit(self):
40 def commit(self):
41 if self._dirty:
41 if self._dirty:
42 f = self._repo.opener("merge/state", "w")
42 f = self._repo.opener("merge/state", "w")
43 f.write(hex(self._local) + "\n")
43 f.write(hex(self._local) + "\n")
44 for d, v in self._state.iteritems():
44 for d, v in self._state.iteritems():
45 f.write("\0".join([d] + v) + "\n")
45 f.write("\0".join([d] + v) + "\n")
46 f.close()
46 f.close()
47 self._dirty = False
47 self._dirty = False
48 def add(self, fcl, fco, fca, fd):
48 def add(self, fcl, fco, fca, fd):
49 hash = util.sha1(fcl.path()).hexdigest()
49 hash = util.sha1(fcl.path()).hexdigest()
50 self._repo.opener.write("merge/" + hash, fcl.data())
50 self._repo.opener.write("merge/" + hash, fcl.data())
51 self._state[fd] = ['u', hash, fcl.path(), fca.path(),
51 self._state[fd] = ['u', hash, fcl.path(), fca.path(),
52 hex(fca.filenode()), fco.path(), fcl.flags()]
52 hex(fca.filenode()), fco.path(), fcl.flags()]
53 self._dirty = True
53 self._dirty = True
54 def __contains__(self, dfile):
54 def __contains__(self, dfile):
55 return dfile in self._state
55 return dfile in self._state
56 def __getitem__(self, dfile):
56 def __getitem__(self, dfile):
57 return self._state[dfile][0]
57 return self._state[dfile][0]
58 def __iter__(self):
58 def __iter__(self):
59 l = self._state.keys()
59 l = self._state.keys()
60 l.sort()
60 l.sort()
61 for f in l:
61 for f in l:
62 yield f
62 yield f
63 def mark(self, dfile, state):
63 def mark(self, dfile, state):
64 self._state[dfile][0] = state
64 self._state[dfile][0] = state
65 self._dirty = True
65 self._dirty = True
66 def resolve(self, dfile, wctx, octx):
66 def resolve(self, dfile, wctx, octx):
67 if self[dfile] == 'r':
67 if self[dfile] == 'r':
68 return 0
68 return 0
69 state, hash, lfile, afile, anode, ofile, flags = self._state[dfile]
69 state, hash, lfile, afile, anode, ofile, flags = self._state[dfile]
70 fcd = wctx[dfile]
70 fcd = wctx[dfile]
71 fco = octx[ofile]
71 fco = octx[ofile]
72 fca = self._repo.filectx(afile, fileid=anode)
72 fca = self._repo.filectx(afile, fileid=anode)
73 # "premerge" x flags
73 # "premerge" x flags
74 flo = fco.flags()
74 flo = fco.flags()
75 fla = fca.flags()
75 fla = fca.flags()
76 if 'x' in flags + flo + fla and 'l' not in flags + flo + fla:
76 if 'x' in flags + flo + fla and 'l' not in flags + flo + fla:
77 if fca.node() == nullid:
77 if fca.node() == nullid:
78 self._repo.ui.warn(_('warning: cannot merge flags for %s\n') %
78 self._repo.ui.warn(_('warning: cannot merge flags for %s\n') %
79 afile)
79 afile)
80 elif flags == fla:
80 elif flags == fla:
81 flags = flo
81 flags = flo
82 # restore local
82 # restore local
83 f = self._repo.opener("merge/" + hash)
83 f = self._repo.opener("merge/" + hash)
84 self._repo.wwrite(dfile, f.read(), flags)
84 self._repo.wwrite(dfile, f.read(), flags)
85 f.close()
85 f.close()
86 r = filemerge.filemerge(self._repo, self._local, lfile, fcd, fco, fca)
86 r = filemerge.filemerge(self._repo, self._local, lfile, fcd, fco, fca)
87 if r is None:
87 if r is None:
88 # no real conflict
88 # no real conflict
89 del self._state[dfile]
89 del self._state[dfile]
90 elif not r:
90 elif not r:
91 self.mark(dfile, 'r')
91 self.mark(dfile, 'r')
92 return r
92 return r
93
93
94 def _checkunknownfile(repo, wctx, mctx, f):
94 def _checkunknownfile(repo, wctx, mctx, f):
95 return (not repo.dirstate._ignore(f)
95 return (not repo.dirstate._ignore(f)
96 and os.path.isfile(repo.wjoin(f))
96 and os.path.isfile(repo.wjoin(f))
97 and repo.dirstate.normalize(f) not in repo.dirstate
97 and repo.dirstate.normalize(f) not in repo.dirstate
98 and mctx[f].cmp(wctx[f]))
98 and mctx[f].cmp(wctx[f]))
99
99
100 def _checkunknown(repo, wctx, mctx):
100 def _checkunknown(repo, wctx, mctx):
101 "check for collisions between unknown files and files in mctx"
101 "check for collisions between unknown files and files in mctx"
102
102
103 error = False
103 error = False
104 for f in mctx:
104 for f in mctx:
105 if f not in wctx and _checkunknownfile(repo, wctx, mctx, f):
105 if f not in wctx and _checkunknownfile(repo, wctx, mctx, f):
106 error = True
106 error = True
107 wctx._repo.ui.warn(_("%s: untracked file differs\n") % f)
107 wctx._repo.ui.warn(_("%s: untracked file differs\n") % f)
108 if error:
108 if error:
109 raise util.Abort(_("untracked files in working directory differ "
109 raise util.Abort(_("untracked files in working directory differ "
110 "from files in requested revision"))
110 "from files in requested revision"))
111
111
112 def _remains(f, m, ma, workingctx=False):
112 def _remains(f, m, ma, workingctx=False):
113 """check whether specified file remains after merge.
113 """check whether specified file remains after merge.
114
114
115 It is assumed that specified file is not contained in the manifest
115 It is assumed that specified file is not contained in the manifest
116 of the other context.
116 of the other context.
117 """
117 """
118 if f in ma:
118 if f in ma:
119 n = m[f]
119 n = m[f]
120 if n != ma[f]:
120 if n != ma[f]:
121 return True # because it is changed locally
121 return True # because it is changed locally
122 # even though it doesn't remain, if "remote deleted" is
122 # even though it doesn't remain, if "remote deleted" is
123 # chosen in manifestmerge()
123 # chosen in manifestmerge()
124 elif workingctx and n[20:] == "a":
124 elif workingctx and n[20:] == "a":
125 return True # because it is added locally (linear merge specific)
125 return True # because it is added locally (linear merge specific)
126 else:
126 else:
127 return False # because it is removed remotely
127 return False # because it is removed remotely
128 else:
128 else:
129 return True # because it is added locally
129 return True # because it is added locally
130
130
131 def _checkcollision(mctx, extractxs):
131 def _checkcollision(mctx, extractxs):
132 "check for case folding collisions in the destination context"
132 "check for case folding collisions in the destination context"
133 folded = {}
133 folded = {}
134 for fn in mctx:
134 for fn in mctx:
135 fold = util.normcase(fn)
135 fold = util.normcase(fn)
136 if fold in folded:
136 if fold in folded:
137 raise util.Abort(_("case-folding collision between %s and %s")
137 raise util.Abort(_("case-folding collision between %s and %s")
138 % (fn, folded[fold]))
138 % (fn, folded[fold]))
139 folded[fold] = fn
139 folded[fold] = fn
140
140
141 if extractxs:
141 if extractxs:
142 wctx, actx = extractxs
142 wctx, actx = extractxs
143 # class to delay looking up copy mapping
143 # class to delay looking up copy mapping
144 class pathcopies(object):
144 class pathcopies(object):
145 @util.propertycache
145 @util.propertycache
146 def map(self):
146 def map(self):
147 # {dst@mctx: src@wctx} copy mapping
147 # {dst@mctx: src@wctx} copy mapping
148 return copies.pathcopies(wctx, mctx)
148 return copies.pathcopies(wctx, mctx)
149 pc = pathcopies()
149 pc = pathcopies()
150
150
151 for fn in wctx:
151 for fn in wctx:
152 fold = util.normcase(fn)
152 fold = util.normcase(fn)
153 mfn = folded.get(fold, None)
153 mfn = folded.get(fold, None)
154 if (mfn and mfn != fn and pc.map.get(mfn) != fn and
154 if (mfn and mfn != fn and pc.map.get(mfn) != fn and
155 _remains(fn, wctx.manifest(), actx.manifest(), True) and
155 _remains(fn, wctx.manifest(), actx.manifest(), True) and
156 _remains(mfn, mctx.manifest(), actx.manifest())):
156 _remains(mfn, mctx.manifest(), actx.manifest())):
157 raise util.Abort(_("case-folding collision between %s and %s")
157 raise util.Abort(_("case-folding collision between %s and %s")
158 % (mfn, fn))
158 % (mfn, fn))
159
159
160 def _forgetremoved(wctx, mctx, branchmerge):
160 def _forgetremoved(wctx, mctx, branchmerge):
161 """
161 """
162 Forget removed files
162 Forget removed files
163
163
164 If we're jumping between revisions (as opposed to merging), and if
164 If we're jumping between revisions (as opposed to merging), and if
165 neither the working directory nor the target rev has the file,
165 neither the working directory nor the target rev has the file,
166 then we need to remove it from the dirstate, to prevent the
166 then we need to remove it from the dirstate, to prevent the
167 dirstate from listing the file when it is no longer in the
167 dirstate from listing the file when it is no longer in the
168 manifest.
168 manifest.
169
169
170 If we're merging, and the other revision has removed a file
170 If we're merging, and the other revision has removed a file
171 that is not present in the working directory, we need to mark it
171 that is not present in the working directory, we need to mark it
172 as removed.
172 as removed.
173 """
173 """
174
174
175 actions = []
175 actions = []
176 state = branchmerge and 'r' or 'f'
176 state = branchmerge and 'r' or 'f'
177 for f in wctx.deleted():
177 for f in wctx.deleted():
178 if f not in mctx:
178 if f not in mctx:
179 actions.append((f, state, None))
179 actions.append((f, state, None, "forget deleted"))
180
180
181 if not branchmerge:
181 if not branchmerge:
182 for f in wctx.removed():
182 for f in wctx.removed():
183 if f not in mctx:
183 if f not in mctx:
184 actions.append((f, "f", None))
184 actions.append((f, "f", None, "forget removed"))
185
185
186 return actions
186 return actions
187
187
188 def manifestmerge(repo, p1, p2, pa, overwrite, partial):
188 def manifestmerge(repo, p1, p2, pa, overwrite, partial):
189 """
189 """
190 Merge p1 and p2 with ancestor pa and generate merge action list
190 Merge p1 and p2 with ancestor pa and generate merge action list
191
191
192 overwrite = whether we clobber working files
192 overwrite = whether we clobber working files
193 partial = function to filter file lists
193 partial = function to filter file lists
194 """
194 """
195
195
196 def act(msg, m, f, *args):
196 def act(msg, m, f, *args):
197 repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m))
197 actions.append((f, m, args, msg))
198 actions.append((f, m, args))
199
198
200 actions, copy, movewithdir = [], {}, {}
199 actions, copy, movewithdir = [], {}, {}
201
200
202 if overwrite:
201 if overwrite:
203 pa = p1
202 pa = p1
204 elif pa == p2: # backwards
203 elif pa == p2: # backwards
205 pa = p1.p1()
204 pa = p1.p1()
206 elif pa and repo.ui.configbool("merge", "followcopies", True):
205 elif pa and repo.ui.configbool("merge", "followcopies", True):
207 ret = copies.mergecopies(repo, p1, p2, pa)
206 ret = copies.mergecopies(repo, p1, p2, pa)
208 copy, movewithdir, diverge, renamedelete = ret
207 copy, movewithdir, diverge, renamedelete = ret
209 for of, fl in diverge.iteritems():
208 for of, fl in diverge.iteritems():
210 act("divergent renames", "dr", of, fl)
209 act("divergent renames", "dr", of, fl)
211 for of, fl in renamedelete.iteritems():
210 for of, fl in renamedelete.iteritems():
212 act("rename and delete", "rd", of, fl)
211 act("rename and delete", "rd", of, fl)
213
212
214 repo.ui.note(_("resolving manifests\n"))
213 repo.ui.note(_("resolving manifests\n"))
215 repo.ui.debug(" overwrite: %s, partial: %s\n"
214 repo.ui.debug(" overwrite: %s, partial: %s\n"
216 % (bool(overwrite), bool(partial)))
215 % (bool(overwrite), bool(partial)))
217 repo.ui.debug(" ancestor: %s, local: %s, remote: %s\n" % (pa, p1, p2))
216 repo.ui.debug(" ancestor: %s, local: %s, remote: %s\n" % (pa, p1, p2))
218
217
219 m1, m2, ma = p1.manifest(), p2.manifest(), pa.manifest()
218 m1, m2, ma = p1.manifest(), p2.manifest(), pa.manifest()
220 copied = set(copy.values())
219 copied = set(copy.values())
221 copied.update(movewithdir.values())
220 copied.update(movewithdir.values())
222
221
223 if '.hgsubstate' in m1:
222 if '.hgsubstate' in m1:
224 # check whether sub state is modified
223 # check whether sub state is modified
225 for s in sorted(p1.substate):
224 for s in sorted(p1.substate):
226 if p1.sub(s).dirty():
225 if p1.sub(s).dirty():
227 m1['.hgsubstate'] += "+"
226 m1['.hgsubstate'] += "+"
228 break
227 break
229
228
230 prompts = []
229 prompts = []
231 # Compare manifests
230 # Compare manifests
232 visit = m1.iteritems()
231 visit = m1.iteritems()
233 if repo.ui.debugflag:
232 if repo.ui.debugflag:
234 visit = sorted(visit)
233 visit = sorted(visit)
235 for f, n in visit:
234 for f, n in visit:
236 if partial and not partial(f):
235 if partial and not partial(f):
237 continue
236 continue
238 if f in m2:
237 if f in m2:
239 n2 = m2[f]
238 n2 = m2[f]
240 fl1, fl2, fla = m1.flags(f), m2.flags(f), ma.flags(f)
239 fl1, fl2, fla = m1.flags(f), m2.flags(f), ma.flags(f)
241 nol = 'l' not in fl1 + fl2 + fla
240 nol = 'l' not in fl1 + fl2 + fla
242 a = ma.get(f, nullid)
241 a = ma.get(f, nullid)
243 if n == n2 and fl1 == fl2:
242 if n == n2 and fl1 == fl2:
244 pass # same - keep local
243 pass # same - keep local
245 elif n2 == a and fl2 == fla:
244 elif n2 == a and fl2 == fla:
246 pass # remote unchanged - keep local
245 pass # remote unchanged - keep local
247 elif n == a and fl1 == fla: # local unchanged - use remote
246 elif n == a and fl1 == fla: # local unchanged - use remote
248 if n == n2: # optimization: keep local content
247 if n == n2: # optimization: keep local content
249 act("update permissions", "e", f, fl2)
248 act("update permissions", "e", f, fl2)
250 else:
249 else:
251 act("remote is newer", "g", f, fl2)
250 act("remote is newer", "g", f, fl2)
252 elif nol and n2 == a: # remote only changed 'x'
251 elif nol and n2 == a: # remote only changed 'x'
253 act("update permissions", "e", f, fl2)
252 act("update permissions", "e", f, fl2)
254 elif nol and n == a: # local only changed 'x'
253 elif nol and n == a: # local only changed 'x'
255 act("remote is newer", "g", f, fl1)
254 act("remote is newer", "g", f, fl1)
256 else: # both changed something
255 else: # both changed something
257 act("versions differ", "m", f, f, f, False)
256 act("versions differ", "m", f, f, f, False)
258 elif f in copied: # files we'll deal with on m2 side
257 elif f in copied: # files we'll deal with on m2 side
259 pass
258 pass
260 elif f in movewithdir: # directory rename
259 elif f in movewithdir: # directory rename
261 f2 = movewithdir[f]
260 f2 = movewithdir[f]
262 act("remote renamed directory to " + f2, "d", f, None, f2,
261 act("remote renamed directory to " + f2, "d", f, None, f2,
263 m1.flags(f))
262 m1.flags(f))
264 elif f in copy:
263 elif f in copy:
265 f2 = copy[f]
264 f2 = copy[f]
266 act("local copied/moved to " + f2, "m", f, f2, f, False)
265 act("local copied/moved to " + f2, "m", f, f2, f, False)
267 elif f in ma: # clean, a different, no remote
266 elif f in ma: # clean, a different, no remote
268 if n != ma[f]:
267 if n != ma[f]:
269 prompts.append((f, "cd")) # prompt changed/deleted
268 prompts.append((f, "cd")) # prompt changed/deleted
270 elif n[20:] == "a": # added, no remote
269 elif n[20:] == "a": # added, no remote
271 act("remote deleted", "f", f)
270 act("remote deleted", "f", f)
272 else:
271 else:
273 act("other deleted", "r", f)
272 act("other deleted", "r", f)
274
273
275 visit = m2.iteritems()
274 visit = m2.iteritems()
276 if repo.ui.debugflag:
275 if repo.ui.debugflag:
277 visit = sorted(visit)
276 visit = sorted(visit)
278 for f, n in visit:
277 for f, n in visit:
279 if partial and not partial(f):
278 if partial and not partial(f):
280 continue
279 continue
281 if f in m1 or f in copied: # files already visited
280 if f in m1 or f in copied: # files already visited
282 continue
281 continue
283 if f in movewithdir:
282 if f in movewithdir:
284 f2 = movewithdir[f]
283 f2 = movewithdir[f]
285 act("local renamed directory to " + f2, "d", None, f, f2,
284 act("local renamed directory to " + f2, "d", None, f, f2,
286 m2.flags(f))
285 m2.flags(f))
287 elif f in copy:
286 elif f in copy:
288 f2 = copy[f]
287 f2 = copy[f]
289 if f2 in m2:
288 if f2 in m2:
290 act("remote copied to " + f, "m",
289 act("remote copied to " + f, "m",
291 f2, f, f, False)
290 f2, f, f, False)
292 else:
291 else:
293 act("remote moved to " + f, "m",
292 act("remote moved to " + f, "m",
294 f2, f, f, True)
293 f2, f, f, True)
295 elif f not in ma:
294 elif f not in ma:
296 if (not overwrite
295 if (not overwrite
297 and _checkunknownfile(repo, p1, p2, f)):
296 and _checkunknownfile(repo, p1, p2, f)):
298 act("remote differs from untracked local",
297 act("remote differs from untracked local",
299 "m", f, f, f, False)
298 "m", f, f, f, False)
300 else:
299 else:
301 act("remote created", "g", f, m2.flags(f))
300 act("remote created", "g", f, m2.flags(f))
302 elif n != ma[f]:
301 elif n != ma[f]:
303 prompts.append((f, "dc")) # prompt deleted/changed
302 prompts.append((f, "dc")) # prompt deleted/changed
304
303
305 for f, m in sorted(prompts):
304 for f, m in sorted(prompts):
306 if m == "cd":
305 if m == "cd":
307 if repo.ui.promptchoice(
306 if repo.ui.promptchoice(
308 _(" local changed %s which remote deleted\n"
307 _(" local changed %s which remote deleted\n"
309 "use (c)hanged version or (d)elete?") % f,
308 "use (c)hanged version or (d)elete?") % f,
310 (_("&Changed"), _("&Delete")), 0):
309 (_("&Changed"), _("&Delete")), 0):
311 act("prompt delete", "r", f)
310 act("prompt delete", "r", f)
312 else:
311 else:
313 act("prompt keep", "a", f)
312 act("prompt keep", "a", f)
314 elif m == "dc":
313 elif m == "dc":
315 if repo.ui.promptchoice(
314 if repo.ui.promptchoice(
316 _("remote changed %s which local deleted\n"
315 _("remote changed %s which local deleted\n"
317 "use (c)hanged version or leave (d)eleted?") % f,
316 "use (c)hanged version or leave (d)eleted?") % f,
318 (_("&Changed"), _("&Deleted")), 0) == 0:
317 (_("&Changed"), _("&Deleted")), 0) == 0:
319 act("prompt recreating", "g", f, m2.flags(f))
318 act("prompt recreating", "g", f, m2.flags(f))
320 else: assert False, m
319 else: assert False, m
321 return actions
320 return actions
322
321
323 def actionkey(a):
322 def actionkey(a):
324 return a[1] == "r" and -1 or 0, a
323 return a[1] == "r" and -1 or 0, a
325
324
326 def applyupdates(repo, actions, wctx, mctx, actx, overwrite):
325 def applyupdates(repo, actions, wctx, mctx, actx, overwrite):
327 """apply the merge action list to the working directory
326 """apply the merge action list to the working directory
328
327
329 wctx is the working copy context
328 wctx is the working copy context
330 mctx is the context to be merged into the working copy
329 mctx is the context to be merged into the working copy
331 actx is the context of the common ancestor
330 actx is the context of the common ancestor
332
331
333 Return a tuple of counts (updated, merged, removed, unresolved) that
332 Return a tuple of counts (updated, merged, removed, unresolved) that
334 describes how many files were affected by the update.
333 describes how many files were affected by the update.
335 """
334 """
336
335
337 updated, merged, removed, unresolved = 0, 0, 0, 0
336 updated, merged, removed, unresolved = 0, 0, 0, 0
338 ms = mergestate(repo)
337 ms = mergestate(repo)
339 ms.reset(wctx.p1().node())
338 ms.reset(wctx.p1().node())
340 moves = []
339 moves = []
341 actions.sort(key=actionkey)
340 actions.sort(key=actionkey)
342
341
343 # prescan for merges
342 # prescan for merges
344 for a in actions:
343 for a in actions:
345 f, m, args = a
344 f, m, args, msg = a
345 repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m))
346 if m == "m": # merge
346 if m == "m": # merge
347 f2, fd, move = args
347 f2, fd, move = args
348 if fd == '.hgsubstate': # merged internally
348 if fd == '.hgsubstate': # merged internally
349 continue
349 continue
350 repo.ui.debug("preserving %s for resolve of %s\n" % (f, fd))
350 repo.ui.debug(" preserving %s for resolve of %s\n" % (f, fd))
351 fcl = wctx[f]
351 fcl = wctx[f]
352 fco = mctx[f2]
352 fco = mctx[f2]
353 if mctx == actx: # backwards, use working dir parent as ancestor
353 if mctx == actx: # backwards, use working dir parent as ancestor
354 if fcl.parents():
354 if fcl.parents():
355 fca = fcl.p1()
355 fca = fcl.p1()
356 else:
356 else:
357 fca = repo.filectx(f, fileid=nullrev)
357 fca = repo.filectx(f, fileid=nullrev)
358 else:
358 else:
359 fca = fcl.ancestor(fco, actx)
359 fca = fcl.ancestor(fco, actx)
360 if not fca:
360 if not fca:
361 fca = repo.filectx(f, fileid=nullrev)
361 fca = repo.filectx(f, fileid=nullrev)
362 ms.add(fcl, fco, fca, fd)
362 ms.add(fcl, fco, fca, fd)
363 if f != fd and move:
363 if f != fd and move:
364 moves.append(f)
364 moves.append(f)
365
365
366 audit = repo.wopener.audit
366 audit = repo.wopener.audit
367
367
368 # remove renamed files after safely stored
368 # remove renamed files after safely stored
369 for f in moves:
369 for f in moves:
370 if os.path.lexists(repo.wjoin(f)):
370 if os.path.lexists(repo.wjoin(f)):
371 repo.ui.debug("removing %s\n" % f)
371 repo.ui.debug("removing %s\n" % f)
372 audit(f)
372 audit(f)
373 util.unlinkpath(repo.wjoin(f))
373 util.unlinkpath(repo.wjoin(f))
374
374
375 numupdates = len(actions)
375 numupdates = len(actions)
376 for i, a in enumerate(actions):
376 for i, a in enumerate(actions):
377 f, m, args = a
377 f, m, args, msg = a
378 repo.ui.progress(_('updating'), i + 1, item=f, total=numupdates,
378 repo.ui.progress(_('updating'), i + 1, item=f, total=numupdates,
379 unit=_('files'))
379 unit=_('files'))
380 if m == "r": # remove
380 if m == "r": # remove
381 repo.ui.note(_("removing %s\n") % f)
381 repo.ui.note(_("removing %s\n") % f)
382 audit(f)
382 audit(f)
383 if f == '.hgsubstate': # subrepo states need updating
383 if f == '.hgsubstate': # subrepo states need updating
384 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
384 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
385 try:
385 try:
386 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
386 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
387 except OSError, inst:
387 except OSError, inst:
388 repo.ui.warn(_("update failed to remove %s: %s!\n") %
388 repo.ui.warn(_("update failed to remove %s: %s!\n") %
389 (f, inst.strerror))
389 (f, inst.strerror))
390 removed += 1
390 removed += 1
391 elif m == "m": # merge
391 elif m == "m": # merge
392 if fd == '.hgsubstate': # subrepo states need updating
392 if fd == '.hgsubstate': # subrepo states need updating
393 subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx),
393 subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx),
394 overwrite)
394 overwrite)
395 continue
395 continue
396 f2, fd, move = args
396 f2, fd, move = args
397 audit(fd)
397 audit(fd)
398 r = ms.resolve(fd, wctx, mctx)
398 r = ms.resolve(fd, wctx, mctx)
399 if r is not None and r > 0:
399 if r is not None and r > 0:
400 unresolved += 1
400 unresolved += 1
401 else:
401 else:
402 if r is None:
402 if r is None:
403 updated += 1
403 updated += 1
404 else:
404 else:
405 merged += 1
405 merged += 1
406 elif m == "g": # get
406 elif m == "g": # get
407 flags, = args
407 flags, = args
408 repo.ui.note(_("getting %s\n") % f)
408 repo.ui.note(_("getting %s\n") % f)
409 repo.wwrite(f, mctx.filectx(f).data(), flags)
409 repo.wwrite(f, mctx.filectx(f).data(), flags)
410 updated += 1
410 updated += 1
411 if f == '.hgsubstate': # subrepo states need updating
411 if f == '.hgsubstate': # subrepo states need updating
412 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
412 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
413 elif m == "d": # directory rename
413 elif m == "d": # directory rename
414 f2, fd, flags = args
414 f2, fd, flags = args
415 if f:
415 if f:
416 repo.ui.note(_("moving %s to %s\n") % (f, fd))
416 repo.ui.note(_("moving %s to %s\n") % (f, fd))
417 audit(f)
417 audit(f)
418 repo.wwrite(fd, wctx.filectx(f).data(), flags)
418 repo.wwrite(fd, wctx.filectx(f).data(), flags)
419 util.unlinkpath(repo.wjoin(f))
419 util.unlinkpath(repo.wjoin(f))
420 if f2:
420 if f2:
421 repo.ui.note(_("getting %s to %s\n") % (f2, fd))
421 repo.ui.note(_("getting %s to %s\n") % (f2, fd))
422 repo.wwrite(fd, mctx.filectx(f2).data(), flags)
422 repo.wwrite(fd, mctx.filectx(f2).data(), flags)
423 updated += 1
423 updated += 1
424 elif m == "dr": # divergent renames
424 elif m == "dr": # divergent renames
425 fl, = args
425 fl, = args
426 repo.ui.warn(_("note: possible conflict - %s was renamed "
426 repo.ui.warn(_("note: possible conflict - %s was renamed "
427 "multiple times to:\n") % f)
427 "multiple times to:\n") % f)
428 for nf in fl:
428 for nf in fl:
429 repo.ui.warn(" %s\n" % nf)
429 repo.ui.warn(" %s\n" % nf)
430 elif m == "rd": # rename and delete
430 elif m == "rd": # rename and delete
431 fl, = args
431 fl, = args
432 repo.ui.warn(_("note: possible conflict - %s was deleted "
432 repo.ui.warn(_("note: possible conflict - %s was deleted "
433 "and renamed to:\n") % f)
433 "and renamed to:\n") % f)
434 for nf in fl:
434 for nf in fl:
435 repo.ui.warn(" %s\n" % nf)
435 repo.ui.warn(" %s\n" % nf)
436 elif m == "e": # exec
436 elif m == "e": # exec
437 flags, = args
437 flags, = args
438 audit(f)
438 audit(f)
439 util.setflags(repo.wjoin(f), 'l' in flags, 'x' in flags)
439 util.setflags(repo.wjoin(f), 'l' in flags, 'x' in flags)
440 updated += 1
440 updated += 1
441 ms.commit()
441 ms.commit()
442 repo.ui.progress(_('updating'), None, total=numupdates, unit=_('files'))
442 repo.ui.progress(_('updating'), None, total=numupdates, unit=_('files'))
443
443
444 return updated, merged, removed, unresolved
444 return updated, merged, removed, unresolved
445
445
446 def calculateupdates(repo, tctx, mctx, ancestor, branchmerge, force, partial):
446 def calculateupdates(repo, tctx, mctx, ancestor, branchmerge, force, partial):
447 "Calculate the actions needed to merge mctx into tctx"
447 "Calculate the actions needed to merge mctx into tctx"
448 actions = []
448 actions = []
449 folding = not util.checkcase(repo.path)
449 folding = not util.checkcase(repo.path)
450 if folding:
450 if folding:
451 # collision check is not needed for clean update
451 # collision check is not needed for clean update
452 if (not branchmerge and
452 if (not branchmerge and
453 (force or not tctx.dirty(missing=True, branch=False))):
453 (force or not tctx.dirty(missing=True, branch=False))):
454 _checkcollision(mctx, None)
454 _checkcollision(mctx, None)
455 else:
455 else:
456 _checkcollision(mctx, (tctx, ancestor))
456 _checkcollision(mctx, (tctx, ancestor))
457 if not force:
457 if not force:
458 _checkunknown(repo, tctx, mctx)
458 _checkunknown(repo, tctx, mctx)
459 if tctx.rev() is None:
459 if tctx.rev() is None:
460 actions += _forgetremoved(tctx, mctx, branchmerge)
460 actions += _forgetremoved(tctx, mctx, branchmerge)
461 actions += manifestmerge(repo, tctx, mctx,
461 actions += manifestmerge(repo, tctx, mctx,
462 ancestor,
462 ancestor,
463 force and not branchmerge,
463 force and not branchmerge,
464 partial)
464 partial)
465 return actions
465 return actions
466
466
467 def recordupdates(repo, actions, branchmerge):
467 def recordupdates(repo, actions, branchmerge):
468 "record merge actions to the dirstate"
468 "record merge actions to the dirstate"
469
469
470 for a in actions:
470 for a in actions:
471 f, m, args = a
471 f, m, args, msg = a
472 if m == "r": # remove
472 if m == "r": # remove
473 if branchmerge:
473 if branchmerge:
474 repo.dirstate.remove(f)
474 repo.dirstate.remove(f)
475 else:
475 else:
476 repo.dirstate.drop(f)
476 repo.dirstate.drop(f)
477 elif m == "a": # re-add
477 elif m == "a": # re-add
478 if not branchmerge:
478 if not branchmerge:
479 repo.dirstate.add(f)
479 repo.dirstate.add(f)
480 elif m == "f": # forget
480 elif m == "f": # forget
481 repo.dirstate.drop(f)
481 repo.dirstate.drop(f)
482 elif m == "e": # exec change
482 elif m == "e": # exec change
483 repo.dirstate.normallookup(f)
483 repo.dirstate.normallookup(f)
484 elif m == "g": # get
484 elif m == "g": # get
485 if branchmerge:
485 if branchmerge:
486 repo.dirstate.otherparent(f)
486 repo.dirstate.otherparent(f)
487 else:
487 else:
488 repo.dirstate.normal(f)
488 repo.dirstate.normal(f)
489 elif m == "m": # merge
489 elif m == "m": # merge
490 f2, fd, move = args
490 f2, fd, move = args
491 if branchmerge:
491 if branchmerge:
492 # We've done a branch merge, mark this file as merged
492 # We've done a branch merge, mark this file as merged
493 # so that we properly record the merger later
493 # so that we properly record the merger later
494 repo.dirstate.merge(fd)
494 repo.dirstate.merge(fd)
495 if f != f2: # copy/rename
495 if f != f2: # copy/rename
496 if move:
496 if move:
497 repo.dirstate.remove(f)
497 repo.dirstate.remove(f)
498 if f != fd:
498 if f != fd:
499 repo.dirstate.copy(f, fd)
499 repo.dirstate.copy(f, fd)
500 else:
500 else:
501 repo.dirstate.copy(f2, fd)
501 repo.dirstate.copy(f2, fd)
502 else:
502 else:
503 # We've update-merged a locally modified file, so
503 # We've update-merged a locally modified file, so
504 # we set the dirstate to emulate a normal checkout
504 # we set the dirstate to emulate a normal checkout
505 # of that file some time in the past. Thus our
505 # of that file some time in the past. Thus our
506 # merge will appear as a normal local file
506 # merge will appear as a normal local file
507 # modification.
507 # modification.
508 if f2 == fd: # file not locally copied/moved
508 if f2 == fd: # file not locally copied/moved
509 repo.dirstate.normallookup(fd)
509 repo.dirstate.normallookup(fd)
510 if move:
510 if move:
511 repo.dirstate.drop(f)
511 repo.dirstate.drop(f)
512 elif m == "d": # directory rename
512 elif m == "d": # directory rename
513 f2, fd, flag = args
513 f2, fd, flag = args
514 if not f2 and f not in repo.dirstate:
514 if not f2 and f not in repo.dirstate:
515 # untracked file moved
515 # untracked file moved
516 continue
516 continue
517 if branchmerge:
517 if branchmerge:
518 repo.dirstate.add(fd)
518 repo.dirstate.add(fd)
519 if f:
519 if f:
520 repo.dirstate.remove(f)
520 repo.dirstate.remove(f)
521 repo.dirstate.copy(f, fd)
521 repo.dirstate.copy(f, fd)
522 if f2:
522 if f2:
523 repo.dirstate.copy(f2, fd)
523 repo.dirstate.copy(f2, fd)
524 else:
524 else:
525 repo.dirstate.normal(fd)
525 repo.dirstate.normal(fd)
526 if f:
526 if f:
527 repo.dirstate.drop(f)
527 repo.dirstate.drop(f)
528
528
529 def update(repo, node, branchmerge, force, partial, ancestor=None,
529 def update(repo, node, branchmerge, force, partial, ancestor=None,
530 mergeancestor=False):
530 mergeancestor=False):
531 """
531 """
532 Perform a merge between the working directory and the given node
532 Perform a merge between the working directory and the given node
533
533
534 node = the node to update to, or None if unspecified
534 node = the node to update to, or None if unspecified
535 branchmerge = whether to merge between branches
535 branchmerge = whether to merge between branches
536 force = whether to force branch merging or file overwriting
536 force = whether to force branch merging or file overwriting
537 partial = a function to filter file lists (dirstate not updated)
537 partial = a function to filter file lists (dirstate not updated)
538 mergeancestor = if false, merging with an ancestor (fast-forward)
538 mergeancestor = if false, merging with an ancestor (fast-forward)
539 is only allowed between different named branches. This flag
539 is only allowed between different named branches. This flag
540 is used by rebase extension as a temporary fix and should be
540 is used by rebase extension as a temporary fix and should be
541 avoided in general.
541 avoided in general.
542
542
543 The table below shows all the behaviors of the update command
543 The table below shows all the behaviors of the update command
544 given the -c and -C or no options, whether the working directory
544 given the -c and -C or no options, whether the working directory
545 is dirty, whether a revision is specified, and the relationship of
545 is dirty, whether a revision is specified, and the relationship of
546 the parent rev to the target rev (linear, on the same named
546 the parent rev to the target rev (linear, on the same named
547 branch, or on another named branch).
547 branch, or on another named branch).
548
548
549 This logic is tested by test-update-branches.t.
549 This logic is tested by test-update-branches.t.
550
550
551 -c -C dirty rev | linear same cross
551 -c -C dirty rev | linear same cross
552 n n n n | ok (1) x
552 n n n n | ok (1) x
553 n n n y | ok ok ok
553 n n n y | ok ok ok
554 n n y * | merge (2) (2)
554 n n y * | merge (2) (2)
555 n y * * | --- discard ---
555 n y * * | --- discard ---
556 y n y * | --- (3) ---
556 y n y * | --- (3) ---
557 y n n * | --- ok ---
557 y n n * | --- ok ---
558 y y * * | --- (4) ---
558 y y * * | --- (4) ---
559
559
560 x = can't happen
560 x = can't happen
561 * = don't-care
561 * = don't-care
562 1 = abort: crosses branches (use 'hg merge' or 'hg update -c')
562 1 = abort: crosses branches (use 'hg merge' or 'hg update -c')
563 2 = abort: crosses branches (use 'hg merge' to merge or
563 2 = abort: crosses branches (use 'hg merge' to merge or
564 use 'hg update -C' to discard changes)
564 use 'hg update -C' to discard changes)
565 3 = abort: uncommitted local changes
565 3 = abort: uncommitted local changes
566 4 = incompatible options (checked in commands.py)
566 4 = incompatible options (checked in commands.py)
567
567
568 Return the same tuple as applyupdates().
568 Return the same tuple as applyupdates().
569 """
569 """
570
570
571 onode = node
571 onode = node
572 wlock = repo.wlock()
572 wlock = repo.wlock()
573 try:
573 try:
574 wc = repo[None]
574 wc = repo[None]
575 if node is None:
575 if node is None:
576 # tip of current branch
576 # tip of current branch
577 try:
577 try:
578 node = repo.branchtip(wc.branch())
578 node = repo.branchtip(wc.branch())
579 except error.RepoLookupError:
579 except error.RepoLookupError:
580 if wc.branch() == "default": # no default branch!
580 if wc.branch() == "default": # no default branch!
581 node = repo.lookup("tip") # update to tip
581 node = repo.lookup("tip") # update to tip
582 else:
582 else:
583 raise util.Abort(_("branch %s not found") % wc.branch())
583 raise util.Abort(_("branch %s not found") % wc.branch())
584 overwrite = force and not branchmerge
584 overwrite = force and not branchmerge
585 pl = wc.parents()
585 pl = wc.parents()
586 p1, p2 = pl[0], repo[node]
586 p1, p2 = pl[0], repo[node]
587 if ancestor:
587 if ancestor:
588 pa = repo[ancestor]
588 pa = repo[ancestor]
589 else:
589 else:
590 pa = p1.ancestor(p2)
590 pa = p1.ancestor(p2)
591
591
592 fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
592 fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
593
593
594 ### check phase
594 ### check phase
595 if not overwrite and len(pl) > 1:
595 if not overwrite and len(pl) > 1:
596 raise util.Abort(_("outstanding uncommitted merges"))
596 raise util.Abort(_("outstanding uncommitted merges"))
597 if branchmerge:
597 if branchmerge:
598 if pa == p2:
598 if pa == p2:
599 raise util.Abort(_("merging with a working directory ancestor"
599 raise util.Abort(_("merging with a working directory ancestor"
600 " has no effect"))
600 " has no effect"))
601 elif pa == p1:
601 elif pa == p1:
602 if not mergeancestor and p1.branch() == p2.branch():
602 if not mergeancestor and p1.branch() == p2.branch():
603 raise util.Abort(_("nothing to merge"),
603 raise util.Abort(_("nothing to merge"),
604 hint=_("use 'hg update' "
604 hint=_("use 'hg update' "
605 "or check 'hg heads'"))
605 "or check 'hg heads'"))
606 if not force and (wc.files() or wc.deleted()):
606 if not force and (wc.files() or wc.deleted()):
607 raise util.Abort(_("outstanding uncommitted changes"),
607 raise util.Abort(_("outstanding uncommitted changes"),
608 hint=_("use 'hg status' to list changes"))
608 hint=_("use 'hg status' to list changes"))
609 for s in sorted(wc.substate):
609 for s in sorted(wc.substate):
610 if wc.sub(s).dirty():
610 if wc.sub(s).dirty():
611 raise util.Abort(_("outstanding uncommitted changes in "
611 raise util.Abort(_("outstanding uncommitted changes in "
612 "subrepository '%s'") % s)
612 "subrepository '%s'") % s)
613
613
614 elif not overwrite:
614 elif not overwrite:
615 if pa == p1 or pa == p2: # linear
615 if pa == p1 or pa == p2: # linear
616 pass # all good
616 pass # all good
617 elif wc.dirty(missing=True):
617 elif wc.dirty(missing=True):
618 raise util.Abort(_("crosses branches (merge branches or use"
618 raise util.Abort(_("crosses branches (merge branches or use"
619 " --clean to discard changes)"))
619 " --clean to discard changes)"))
620 elif onode is None:
620 elif onode is None:
621 raise util.Abort(_("crosses branches (merge branches or update"
621 raise util.Abort(_("crosses branches (merge branches or update"
622 " --check to force update)"))
622 " --check to force update)"))
623 else:
623 else:
624 # Allow jumping branches if clean and specific rev given
624 # Allow jumping branches if clean and specific rev given
625 pa = p1
625 pa = p1
626
626
627 ### calculate phase
627 ### calculate phase
628 actions = calculateupdates(repo, wc, p2, pa,
628 actions = calculateupdates(repo, wc, p2, pa,
629 branchmerge, force, partial)
629 branchmerge, force, partial)
630
630
631 ### apply phase
631 ### apply phase
632 if not branchmerge: # just jump to the new rev
632 if not branchmerge: # just jump to the new rev
633 fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
633 fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
634 if not partial:
634 if not partial:
635 repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
635 repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
636
636
637 stats = applyupdates(repo, actions, wc, p2, pa, overwrite)
637 stats = applyupdates(repo, actions, wc, p2, pa, overwrite)
638
638
639 if not partial:
639 if not partial:
640 repo.setparents(fp1, fp2)
640 repo.setparents(fp1, fp2)
641 recordupdates(repo, actions, branchmerge)
641 recordupdates(repo, actions, branchmerge)
642 if not branchmerge:
642 if not branchmerge:
643 repo.dirstate.setbranch(p2.branch())
643 repo.dirstate.setbranch(p2.branch())
644 finally:
644 finally:
645 wlock.release()
645 wlock.release()
646
646
647 if not partial:
647 if not partial:
648 repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
648 repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
649 return stats
649 return stats
@@ -1,64 +1,64 b''
1 $ hg init t
1 $ hg init t
2 $ cd t
2 $ cd t
3
3
4 $ echo 1 > a
4 $ echo 1 > a
5 $ hg ci -qAm "first"
5 $ hg ci -qAm "first"
6
6
7 $ hg cp a b
7 $ hg cp a b
8 $ hg mv a c
8 $ hg mv a c
9 $ echo 2 >> b
9 $ echo 2 >> b
10 $ echo 2 >> c
10 $ echo 2 >> c
11
11
12 $ hg ci -qAm "second"
12 $ hg ci -qAm "second"
13
13
14 $ hg co -C 0
14 $ hg co -C 0
15 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
15 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
16
16
17 $ echo 0 > a
17 $ echo 0 > a
18 $ echo 1 >> a
18 $ echo 1 >> a
19
19
20 $ hg ci -qAm "other"
20 $ hg ci -qAm "other"
21
21
22 $ hg merge --debug
22 $ hg merge --debug
23 searching for copies back to rev 1
23 searching for copies back to rev 1
24 unmatched files in other:
24 unmatched files in other:
25 b
25 b
26 c
26 c
27 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
27 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
28 src: 'a' -> dst: 'b' *
28 src: 'a' -> dst: 'b' *
29 src: 'a' -> dst: 'c' *
29 src: 'a' -> dst: 'c' *
30 checking for directory renames
30 checking for directory renames
31 resolving manifests
31 resolving manifests
32 overwrite: False, partial: False
32 overwrite: False, partial: False
33 ancestor: b8bf91eeebbc, local: add3f11052fa+, remote: 17c05bb7fcb6
33 ancestor: b8bf91eeebbc, local: add3f11052fa+, remote: 17c05bb7fcb6
34 a: remote moved to b -> m
34 a: remote moved to b -> m
35 preserving a for resolve of b
35 a: remote moved to c -> m
36 a: remote moved to c -> m
36 preserving a for resolve of b
37 preserving a for resolve of c
37 preserving a for resolve of c
38 removing a
38 removing a
39 updating: a 1/2 files (50.00%)
39 updating: a 1/2 files (50.00%)
40 picked tool 'internal:merge' for b (binary False symlink False)
40 picked tool 'internal:merge' for b (binary False symlink False)
41 merging a and b to b
41 merging a and b to b
42 my b@add3f11052fa+ other b@17c05bb7fcb6 ancestor a@b8bf91eeebbc
42 my b@add3f11052fa+ other b@17c05bb7fcb6 ancestor a@b8bf91eeebbc
43 premerge successful
43 premerge successful
44 updating: a 2/2 files (100.00%)
44 updating: a 2/2 files (100.00%)
45 picked tool 'internal:merge' for c (binary False symlink False)
45 picked tool 'internal:merge' for c (binary False symlink False)
46 merging a and c to c
46 merging a and c to c
47 my c@add3f11052fa+ other c@17c05bb7fcb6 ancestor a@b8bf91eeebbc
47 my c@add3f11052fa+ other c@17c05bb7fcb6 ancestor a@b8bf91eeebbc
48 premerge successful
48 premerge successful
49 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
49 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
50 (branch merge, don't forget to commit)
50 (branch merge, don't forget to commit)
51
51
52 file b
52 file b
53 $ cat b
53 $ cat b
54 0
54 0
55 1
55 1
56 2
56 2
57
57
58 file c
58 file c
59 $ cat c
59 $ cat c
60 0
60 0
61 1
61 1
62 2
62 2
63
63
64 $ cd ..
64 $ cd ..
@@ -1,67 +1,67 b''
1 $ hg init repo
1 $ hg init repo
2 $ cd repo
2 $ cd repo
3
3
4 $ echo line 1 > foo
4 $ echo line 1 > foo
5 $ hg ci -qAm 'add foo'
5 $ hg ci -qAm 'add foo'
6
6
7 copy foo to bar and change both files
7 copy foo to bar and change both files
8 $ hg cp foo bar
8 $ hg cp foo bar
9 $ echo line 2-1 >> foo
9 $ echo line 2-1 >> foo
10 $ echo line 2-2 >> bar
10 $ echo line 2-2 >> bar
11 $ hg ci -m 'cp foo bar; change both'
11 $ hg ci -m 'cp foo bar; change both'
12
12
13 in another branch, change foo in a way that doesn't conflict with
13 in another branch, change foo in a way that doesn't conflict with
14 the other changes
14 the other changes
15 $ hg up -qC 0
15 $ hg up -qC 0
16 $ echo line 0 > foo
16 $ echo line 0 > foo
17 $ hg cat foo >> foo
17 $ hg cat foo >> foo
18 $ hg ci -m 'change foo'
18 $ hg ci -m 'change foo'
19 created new head
19 created new head
20
20
21 we get conflicts that shouldn't be there
21 we get conflicts that shouldn't be there
22 $ hg merge -P
22 $ hg merge -P
23 changeset: 1:484bf6903104
23 changeset: 1:484bf6903104
24 user: test
24 user: test
25 date: Thu Jan 01 00:00:00 1970 +0000
25 date: Thu Jan 01 00:00:00 1970 +0000
26 summary: cp foo bar; change both
26 summary: cp foo bar; change both
27
27
28 $ hg merge --debug
28 $ hg merge --debug
29 searching for copies back to rev 1
29 searching for copies back to rev 1
30 unmatched files in other:
30 unmatched files in other:
31 bar
31 bar
32 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
32 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
33 src: 'foo' -> dst: 'bar' *
33 src: 'foo' -> dst: 'bar' *
34 checking for directory renames
34 checking for directory renames
35 resolving manifests
35 resolving manifests
36 overwrite: False, partial: False
36 overwrite: False, partial: False
37 ancestor: e6dc8efe11cc, local: 6a0df1dad128+, remote: 484bf6903104
37 ancestor: e6dc8efe11cc, local: 6a0df1dad128+, remote: 484bf6903104
38 foo: remote copied to bar -> m
39 preserving foo for resolve of bar
38 foo: versions differ -> m
40 foo: versions differ -> m
39 foo: remote copied to bar -> m
41 preserving foo for resolve of foo
40 preserving foo for resolve of bar
41 preserving foo for resolve of foo
42 updating: foo 1/2 files (50.00%)
42 updating: foo 1/2 files (50.00%)
43 picked tool 'internal:merge' for bar (binary False symlink False)
43 picked tool 'internal:merge' for bar (binary False symlink False)
44 merging foo and bar to bar
44 merging foo and bar to bar
45 my bar@6a0df1dad128+ other bar@484bf6903104 ancestor foo@e6dc8efe11cc
45 my bar@6a0df1dad128+ other bar@484bf6903104 ancestor foo@e6dc8efe11cc
46 premerge successful
46 premerge successful
47 updating: foo 2/2 files (100.00%)
47 updating: foo 2/2 files (100.00%)
48 picked tool 'internal:merge' for foo (binary False symlink False)
48 picked tool 'internal:merge' for foo (binary False symlink False)
49 merging foo
49 merging foo
50 my foo@6a0df1dad128+ other foo@484bf6903104 ancestor foo@e6dc8efe11cc
50 my foo@6a0df1dad128+ other foo@484bf6903104 ancestor foo@e6dc8efe11cc
51 premerge successful
51 premerge successful
52 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
52 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
53 (branch merge, don't forget to commit)
53 (branch merge, don't forget to commit)
54
54
55 contents of foo
55 contents of foo
56 $ cat foo
56 $ cat foo
57 line 0
57 line 0
58 line 1
58 line 1
59 line 2-1
59 line 2-1
60
60
61 contents of bar
61 contents of bar
62 $ cat bar
62 $ cat bar
63 line 0
63 line 0
64 line 1
64 line 1
65 line 2-2
65 line 2-2
66
66
67 $ cd ..
67 $ cd ..
@@ -1,535 +1,535 b''
1 Create a repo with some stuff in it:
1 Create a repo with some stuff in it:
2
2
3 $ hg init a
3 $ hg init a
4 $ cd a
4 $ cd a
5 $ echo a > a
5 $ echo a > a
6 $ echo a > d
6 $ echo a > d
7 $ echo a > e
7 $ echo a > e
8 $ hg ci -qAm0
8 $ hg ci -qAm0
9 $ echo b > a
9 $ echo b > a
10 $ hg ci -m1 -u bar
10 $ hg ci -m1 -u bar
11 $ hg mv a b
11 $ hg mv a b
12 $ hg ci -m2
12 $ hg ci -m2
13 $ hg cp b c
13 $ hg cp b c
14 $ hg ci -m3 -u baz
14 $ hg ci -m3 -u baz
15 $ echo b > d
15 $ echo b > d
16 $ echo f > e
16 $ echo f > e
17 $ hg ci -m4
17 $ hg ci -m4
18 $ hg up -q 3
18 $ hg up -q 3
19 $ echo b > e
19 $ echo b > e
20 $ hg branch -q stable
20 $ hg branch -q stable
21 $ hg ci -m5
21 $ hg ci -m5
22 $ hg merge -q default --tool internal:local
22 $ hg merge -q default --tool internal:local
23 $ hg branch -q default
23 $ hg branch -q default
24 $ hg ci -m6
24 $ hg ci -m6
25 $ hg phase --public 3
25 $ hg phase --public 3
26 $ hg phase --force --secret 6
26 $ hg phase --force --secret 6
27
27
28 $ hg --config extensions.graphlog= log -G --template '{author}@{rev}.{phase}: {desc}\n'
28 $ hg --config extensions.graphlog= log -G --template '{author}@{rev}.{phase}: {desc}\n'
29 @ test@6.secret: 6
29 @ test@6.secret: 6
30 |\
30 |\
31 | o test@5.draft: 5
31 | o test@5.draft: 5
32 | |
32 | |
33 o | test@4.draft: 4
33 o | test@4.draft: 4
34 |/
34 |/
35 o baz@3.public: 3
35 o baz@3.public: 3
36 |
36 |
37 o test@2.public: 2
37 o test@2.public: 2
38 |
38 |
39 o bar@1.public: 1
39 o bar@1.public: 1
40 |
40 |
41 o test@0.public: 0
41 o test@0.public: 0
42
42
43
43
44 Need to specify a rev:
44 Need to specify a rev:
45
45
46 $ hg graft
46 $ hg graft
47 abort: no revisions specified
47 abort: no revisions specified
48 [255]
48 [255]
49
49
50 Can't graft ancestor:
50 Can't graft ancestor:
51
51
52 $ hg graft 1 2
52 $ hg graft 1 2
53 skipping ancestor revision 1
53 skipping ancestor revision 1
54 skipping ancestor revision 2
54 skipping ancestor revision 2
55 [255]
55 [255]
56
56
57 Specify revisions with -r:
57 Specify revisions with -r:
58
58
59 $ hg graft -r 1 -r 2
59 $ hg graft -r 1 -r 2
60 skipping ancestor revision 1
60 skipping ancestor revision 1
61 skipping ancestor revision 2
61 skipping ancestor revision 2
62 [255]
62 [255]
63
63
64 $ hg graft -r 1 2
64 $ hg graft -r 1 2
65 skipping ancestor revision 2
65 skipping ancestor revision 2
66 skipping ancestor revision 1
66 skipping ancestor revision 1
67 [255]
67 [255]
68
68
69 Can't graft with dirty wd:
69 Can't graft with dirty wd:
70
70
71 $ hg up -q 0
71 $ hg up -q 0
72 $ echo foo > a
72 $ echo foo > a
73 $ hg graft 1
73 $ hg graft 1
74 abort: outstanding uncommitted changes
74 abort: outstanding uncommitted changes
75 [255]
75 [255]
76 $ hg revert a
76 $ hg revert a
77
77
78 Graft a rename:
78 Graft a rename:
79
79
80 $ hg graft 2 -u foo
80 $ hg graft 2 -u foo
81 grafting revision 2
81 grafting revision 2
82 merging a and b to b
82 merging a and b to b
83 $ hg export tip --git
83 $ hg export tip --git
84 # HG changeset patch
84 # HG changeset patch
85 # User foo
85 # User foo
86 # Date 0 0
86 # Date 0 0
87 # Node ID ef0ef43d49e79e81ddafdc7997401ba0041efc82
87 # Node ID ef0ef43d49e79e81ddafdc7997401ba0041efc82
88 # Parent 68795b066622ca79a25816a662041d8f78f3cd9e
88 # Parent 68795b066622ca79a25816a662041d8f78f3cd9e
89 2
89 2
90
90
91 diff --git a/a b/b
91 diff --git a/a b/b
92 rename from a
92 rename from a
93 rename to b
93 rename to b
94
94
95 Look for extra:source
95 Look for extra:source
96
96
97 $ hg log --debug -r tip
97 $ hg log --debug -r tip
98 changeset: 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
98 changeset: 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
99 tag: tip
99 tag: tip
100 phase: draft
100 phase: draft
101 parent: 0:68795b066622ca79a25816a662041d8f78f3cd9e
101 parent: 0:68795b066622ca79a25816a662041d8f78f3cd9e
102 parent: -1:0000000000000000000000000000000000000000
102 parent: -1:0000000000000000000000000000000000000000
103 manifest: 7:e59b6b228f9cbf9903d5e9abf996e083a1f533eb
103 manifest: 7:e59b6b228f9cbf9903d5e9abf996e083a1f533eb
104 user: foo
104 user: foo
105 date: Thu Jan 01 00:00:00 1970 +0000
105 date: Thu Jan 01 00:00:00 1970 +0000
106 files+: b
106 files+: b
107 files-: a
107 files-: a
108 extra: branch=default
108 extra: branch=default
109 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
109 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
110 description:
110 description:
111 2
111 2
112
112
113
113
114
114
115 Graft out of order, skipping a merge and a duplicate
115 Graft out of order, skipping a merge and a duplicate
116
116
117 $ hg graft 1 5 4 3 'merge()' 2 -n
117 $ hg graft 1 5 4 3 'merge()' 2 -n
118 skipping ungraftable merge revision 6
118 skipping ungraftable merge revision 6
119 skipping already grafted revision 2
119 skipping already grafted revision 2
120 grafting revision 1
120 grafting revision 1
121 grafting revision 5
121 grafting revision 5
122 grafting revision 4
122 grafting revision 4
123 grafting revision 3
123 grafting revision 3
124
124
125 $ hg graft 1 5 4 3 'merge()' 2 --debug
125 $ hg graft 1 5 4 3 'merge()' 2 --debug
126 skipping ungraftable merge revision 6
126 skipping ungraftable merge revision 6
127 scanning for duplicate grafts
127 scanning for duplicate grafts
128 skipping already grafted revision 2
128 skipping already grafted revision 2
129 grafting revision 1
129 grafting revision 1
130 searching for copies back to rev 1
130 searching for copies back to rev 1
131 unmatched files in local:
131 unmatched files in local:
132 b
132 b
133 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
133 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
134 src: 'a' -> dst: 'b' *
134 src: 'a' -> dst: 'b' *
135 checking for directory renames
135 checking for directory renames
136 resolving manifests
136 resolving manifests
137 overwrite: False, partial: False
137 overwrite: False, partial: False
138 ancestor: 68795b066622, local: ef0ef43d49e7+, remote: 5d205f8b35b6
138 ancestor: 68795b066622, local: ef0ef43d49e7+, remote: 5d205f8b35b6
139 b: local copied/moved to a -> m
139 b: local copied/moved to a -> m
140 preserving b for resolve of b
140 preserving b for resolve of b
141 updating: b 1/1 files (100.00%)
141 updating: b 1/1 files (100.00%)
142 picked tool 'internal:merge' for b (binary False symlink False)
142 picked tool 'internal:merge' for b (binary False symlink False)
143 merging b and a to b
143 merging b and a to b
144 my b@ef0ef43d49e7+ other a@5d205f8b35b6 ancestor a@68795b066622
144 my b@ef0ef43d49e7+ other a@5d205f8b35b6 ancestor a@68795b066622
145 premerge successful
145 premerge successful
146 b
146 b
147 grafting revision 5
147 grafting revision 5
148 searching for copies back to rev 1
148 searching for copies back to rev 1
149 resolving manifests
149 resolving manifests
150 overwrite: False, partial: False
150 overwrite: False, partial: False
151 ancestor: 4c60f11aa304, local: 6b9e5368ca4e+, remote: 97f8bfe72746
151 ancestor: 4c60f11aa304, local: 6b9e5368ca4e+, remote: 97f8bfe72746
152 e: remote is newer -> g
152 e: remote is newer -> g
153 updating: e 1/1 files (100.00%)
153 updating: e 1/1 files (100.00%)
154 getting e
154 getting e
155 e
155 e
156 grafting revision 4
156 grafting revision 4
157 searching for copies back to rev 1
157 searching for copies back to rev 1
158 resolving manifests
158 resolving manifests
159 overwrite: False, partial: False
159 overwrite: False, partial: False
160 ancestor: 4c60f11aa304, local: 1905859650ec+, remote: 9c233e8e184d
160 ancestor: 4c60f11aa304, local: 1905859650ec+, remote: 9c233e8e184d
161 d: remote is newer -> g
161 d: remote is newer -> g
162 e: versions differ -> m
162 e: versions differ -> m
163 preserving e for resolve of e
163 preserving e for resolve of e
164 updating: d 1/2 files (50.00%)
164 updating: d 1/2 files (50.00%)
165 getting d
165 getting d
166 updating: e 2/2 files (100.00%)
166 updating: e 2/2 files (100.00%)
167 picked tool 'internal:merge' for e (binary False symlink False)
167 picked tool 'internal:merge' for e (binary False symlink False)
168 merging e
168 merging e
169 my e@1905859650ec+ other e@9c233e8e184d ancestor e@68795b066622
169 my e@1905859650ec+ other e@9c233e8e184d ancestor e@68795b066622
170 warning: conflicts during merge.
170 warning: conflicts during merge.
171 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
171 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
172 abort: unresolved conflicts, can't continue
172 abort: unresolved conflicts, can't continue
173 (use hg resolve and hg graft --continue)
173 (use hg resolve and hg graft --continue)
174 [255]
174 [255]
175
175
176 Continue without resolve should fail:
176 Continue without resolve should fail:
177
177
178 $ hg graft -c
178 $ hg graft -c
179 grafting revision 4
179 grafting revision 4
180 abort: unresolved merge conflicts (see hg help resolve)
180 abort: unresolved merge conflicts (see hg help resolve)
181 [255]
181 [255]
182
182
183 Fix up:
183 Fix up:
184
184
185 $ echo b > e
185 $ echo b > e
186 $ hg resolve -m e
186 $ hg resolve -m e
187
187
188 Continue with a revision should fail:
188 Continue with a revision should fail:
189
189
190 $ hg graft -c 6
190 $ hg graft -c 6
191 abort: can't specify --continue and revisions
191 abort: can't specify --continue and revisions
192 [255]
192 [255]
193
193
194 $ hg graft -c -r 6
194 $ hg graft -c -r 6
195 abort: can't specify --continue and revisions
195 abort: can't specify --continue and revisions
196 [255]
196 [255]
197
197
198 Continue for real, clobber usernames
198 Continue for real, clobber usernames
199
199
200 $ hg graft -c -U
200 $ hg graft -c -U
201 grafting revision 4
201 grafting revision 4
202 grafting revision 3
202 grafting revision 3
203
203
204 Compare with original:
204 Compare with original:
205
205
206 $ hg diff -r 6
206 $ hg diff -r 6
207 $ hg status --rev 0:. -C
207 $ hg status --rev 0:. -C
208 M d
208 M d
209 M e
209 M e
210 A b
210 A b
211 a
211 a
212 A c
212 A c
213 a
213 a
214 R a
214 R a
215
215
216 View graph:
216 View graph:
217
217
218 $ hg --config extensions.graphlog= log -G --template '{author}@{rev}.{phase}: {desc}\n'
218 $ hg --config extensions.graphlog= log -G --template '{author}@{rev}.{phase}: {desc}\n'
219 @ test@11.draft: 3
219 @ test@11.draft: 3
220 |
220 |
221 o test@10.draft: 4
221 o test@10.draft: 4
222 |
222 |
223 o test@9.draft: 5
223 o test@9.draft: 5
224 |
224 |
225 o bar@8.draft: 1
225 o bar@8.draft: 1
226 |
226 |
227 o foo@7.draft: 2
227 o foo@7.draft: 2
228 |
228 |
229 | o test@6.secret: 6
229 | o test@6.secret: 6
230 | |\
230 | |\
231 | | o test@5.draft: 5
231 | | o test@5.draft: 5
232 | | |
232 | | |
233 | o | test@4.draft: 4
233 | o | test@4.draft: 4
234 | |/
234 | |/
235 | o baz@3.public: 3
235 | o baz@3.public: 3
236 | |
236 | |
237 | o test@2.public: 2
237 | o test@2.public: 2
238 | |
238 | |
239 | o bar@1.public: 1
239 | o bar@1.public: 1
240 |/
240 |/
241 o test@0.public: 0
241 o test@0.public: 0
242
242
243 Graft again onto another branch should preserve the original source
243 Graft again onto another branch should preserve the original source
244 $ hg up -q 0
244 $ hg up -q 0
245 $ echo 'g'>g
245 $ echo 'g'>g
246 $ hg add g
246 $ hg add g
247 $ hg ci -m 7
247 $ hg ci -m 7
248 created new head
248 created new head
249 $ hg graft 7
249 $ hg graft 7
250 grafting revision 7
250 grafting revision 7
251
251
252 $ hg log -r 7 --template '{rev}:{node}\n'
252 $ hg log -r 7 --template '{rev}:{node}\n'
253 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
253 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
254 $ hg log -r 2 --template '{rev}:{node}\n'
254 $ hg log -r 2 --template '{rev}:{node}\n'
255 2:5c095ad7e90f871700f02dd1fa5012cb4498a2d4
255 2:5c095ad7e90f871700f02dd1fa5012cb4498a2d4
256
256
257 $ hg log --debug -r tip
257 $ hg log --debug -r tip
258 changeset: 13:9db0f28fd3747e92c57d015f53b5593aeec53c2d
258 changeset: 13:9db0f28fd3747e92c57d015f53b5593aeec53c2d
259 tag: tip
259 tag: tip
260 phase: draft
260 phase: draft
261 parent: 12:b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
261 parent: 12:b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
262 parent: -1:0000000000000000000000000000000000000000
262 parent: -1:0000000000000000000000000000000000000000
263 manifest: 13:dc313617b8c32457c0d589e0dbbedfe71f3cd637
263 manifest: 13:dc313617b8c32457c0d589e0dbbedfe71f3cd637
264 user: foo
264 user: foo
265 date: Thu Jan 01 00:00:00 1970 +0000
265 date: Thu Jan 01 00:00:00 1970 +0000
266 files+: b
266 files+: b
267 files-: a
267 files-: a
268 extra: branch=default
268 extra: branch=default
269 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
269 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
270 description:
270 description:
271 2
271 2
272
272
273
273
274 Disallow grafting an already grafted cset onto its original branch
274 Disallow grafting an already grafted cset onto its original branch
275 $ hg up -q 6
275 $ hg up -q 6
276 $ hg graft 7
276 $ hg graft 7
277 skipping already grafted revision 7 (was grafted from 2)
277 skipping already grafted revision 7 (was grafted from 2)
278 [255]
278 [255]
279
279
280 Disallow grafting already grafted csets with the same origin onto each other
280 Disallow grafting already grafted csets with the same origin onto each other
281 $ hg up -q 13
281 $ hg up -q 13
282 $ hg graft 2
282 $ hg graft 2
283 skipping already grafted revision 2
283 skipping already grafted revision 2
284 [255]
284 [255]
285 $ hg graft 7
285 $ hg graft 7
286 skipping already grafted revision 7 (same origin 2)
286 skipping already grafted revision 7 (same origin 2)
287 [255]
287 [255]
288
288
289 $ hg up -q 7
289 $ hg up -q 7
290 $ hg graft 2
290 $ hg graft 2
291 skipping already grafted revision 2
291 skipping already grafted revision 2
292 [255]
292 [255]
293 $ hg graft tip
293 $ hg graft tip
294 skipping already grafted revision 13 (same origin 2)
294 skipping already grafted revision 13 (same origin 2)
295 [255]
295 [255]
296
296
297 Graft with --log
297 Graft with --log
298
298
299 $ hg up -Cq 1
299 $ hg up -Cq 1
300 $ hg graft 3 --log -u foo
300 $ hg graft 3 --log -u foo
301 grafting revision 3
301 grafting revision 3
302 warning: can't find ancestor for 'c' copied from 'b'!
302 warning: can't find ancestor for 'c' copied from 'b'!
303 $ hg log --template '{rev} {parents} {desc}\n' -r tip
303 $ hg log --template '{rev} {parents} {desc}\n' -r tip
304 14 1:5d205f8b35b6 3
304 14 1:5d205f8b35b6 3
305 (grafted from 4c60f11aa304a54ae1c199feb94e7fc771e51ed8)
305 (grafted from 4c60f11aa304a54ae1c199feb94e7fc771e51ed8)
306
306
307 Resolve conflicted graft
307 Resolve conflicted graft
308 $ hg up -q 0
308 $ hg up -q 0
309 $ echo b > a
309 $ echo b > a
310 $ hg ci -m 8
310 $ hg ci -m 8
311 created new head
311 created new head
312 $ echo a > a
312 $ echo a > a
313 $ hg ci -m 9
313 $ hg ci -m 9
314 $ hg graft 1 --tool internal:fail
314 $ hg graft 1 --tool internal:fail
315 grafting revision 1
315 grafting revision 1
316 abort: unresolved conflicts, can't continue
316 abort: unresolved conflicts, can't continue
317 (use hg resolve and hg graft --continue)
317 (use hg resolve and hg graft --continue)
318 [255]
318 [255]
319 $ hg resolve --all
319 $ hg resolve --all
320 merging a
320 merging a
321 $ hg graft -c
321 $ hg graft -c
322 grafting revision 1
322 grafting revision 1
323 $ hg export tip --git
323 $ hg export tip --git
324 # HG changeset patch
324 # HG changeset patch
325 # User bar
325 # User bar
326 # Date 0 0
326 # Date 0 0
327 # Node ID 64ecd9071ce83c6e62f538d8ce7709d53f32ebf7
327 # Node ID 64ecd9071ce83c6e62f538d8ce7709d53f32ebf7
328 # Parent 4bdb9a9d0b84ffee1d30f0dfc7744cade17aa19c
328 # Parent 4bdb9a9d0b84ffee1d30f0dfc7744cade17aa19c
329 1
329 1
330
330
331 diff --git a/a b/a
331 diff --git a/a b/a
332 --- a/a
332 --- a/a
333 +++ b/a
333 +++ b/a
334 @@ -1,1 +1,1 @@
334 @@ -1,1 +1,1 @@
335 -a
335 -a
336 +b
336 +b
337
337
338 Resolve conflicted graft with rename
338 Resolve conflicted graft with rename
339 $ echo c > a
339 $ echo c > a
340 $ hg ci -m 10
340 $ hg ci -m 10
341 $ hg graft 2 --tool internal:fail
341 $ hg graft 2 --tool internal:fail
342 grafting revision 2
342 grafting revision 2
343 abort: unresolved conflicts, can't continue
343 abort: unresolved conflicts, can't continue
344 (use hg resolve and hg graft --continue)
344 (use hg resolve and hg graft --continue)
345 [255]
345 [255]
346 $ hg resolve --all
346 $ hg resolve --all
347 merging a and b to b
347 merging a and b to b
348 $ hg graft -c
348 $ hg graft -c
349 grafting revision 2
349 grafting revision 2
350 $ hg export tip --git
350 $ hg export tip --git
351 # HG changeset patch
351 # HG changeset patch
352 # User test
352 # User test
353 # Date 0 0
353 # Date 0 0
354 # Node ID 2e80e1351d6ed50302fe1e05f8bd1d4d412b6e11
354 # Node ID 2e80e1351d6ed50302fe1e05f8bd1d4d412b6e11
355 # Parent e5a51ae854a8bbaaf25cc5c6a57ff46042dadbb4
355 # Parent e5a51ae854a8bbaaf25cc5c6a57ff46042dadbb4
356 2
356 2
357
357
358 diff --git a/a b/b
358 diff --git a/a b/b
359 rename from a
359 rename from a
360 rename to b
360 rename to b
361
361
362 Test simple origin(), with and without args
362 Test simple origin(), with and without args
363 $ hg log -r 'origin()'
363 $ hg log -r 'origin()'
364 changeset: 1:5d205f8b35b6
364 changeset: 1:5d205f8b35b6
365 user: bar
365 user: bar
366 date: Thu Jan 01 00:00:00 1970 +0000
366 date: Thu Jan 01 00:00:00 1970 +0000
367 summary: 1
367 summary: 1
368
368
369 changeset: 2:5c095ad7e90f
369 changeset: 2:5c095ad7e90f
370 user: test
370 user: test
371 date: Thu Jan 01 00:00:00 1970 +0000
371 date: Thu Jan 01 00:00:00 1970 +0000
372 summary: 2
372 summary: 2
373
373
374 changeset: 3:4c60f11aa304
374 changeset: 3:4c60f11aa304
375 user: baz
375 user: baz
376 date: Thu Jan 01 00:00:00 1970 +0000
376 date: Thu Jan 01 00:00:00 1970 +0000
377 summary: 3
377 summary: 3
378
378
379 changeset: 4:9c233e8e184d
379 changeset: 4:9c233e8e184d
380 user: test
380 user: test
381 date: Thu Jan 01 00:00:00 1970 +0000
381 date: Thu Jan 01 00:00:00 1970 +0000
382 summary: 4
382 summary: 4
383
383
384 changeset: 5:97f8bfe72746
384 changeset: 5:97f8bfe72746
385 branch: stable
385 branch: stable
386 parent: 3:4c60f11aa304
386 parent: 3:4c60f11aa304
387 user: test
387 user: test
388 date: Thu Jan 01 00:00:00 1970 +0000
388 date: Thu Jan 01 00:00:00 1970 +0000
389 summary: 5
389 summary: 5
390
390
391 $ hg log -r 'origin(7)'
391 $ hg log -r 'origin(7)'
392 changeset: 2:5c095ad7e90f
392 changeset: 2:5c095ad7e90f
393 user: test
393 user: test
394 date: Thu Jan 01 00:00:00 1970 +0000
394 date: Thu Jan 01 00:00:00 1970 +0000
395 summary: 2
395 summary: 2
396
396
397 Now transplant a graft to test following through copies
397 Now transplant a graft to test following through copies
398 $ hg up -q 0
398 $ hg up -q 0
399 $ hg branch -q dev
399 $ hg branch -q dev
400 $ hg ci -qm "dev branch"
400 $ hg ci -qm "dev branch"
401 $ hg --config extensions.transplant= transplant -q 7
401 $ hg --config extensions.transplant= transplant -q 7
402 $ hg log -r 'origin(.)'
402 $ hg log -r 'origin(.)'
403 changeset: 2:5c095ad7e90f
403 changeset: 2:5c095ad7e90f
404 user: test
404 user: test
405 date: Thu Jan 01 00:00:00 1970 +0000
405 date: Thu Jan 01 00:00:00 1970 +0000
406 summary: 2
406 summary: 2
407
407
408 Test simple destination
408 Test simple destination
409 $ hg log -r 'destination()'
409 $ hg log -r 'destination()'
410 changeset: 7:ef0ef43d49e7
410 changeset: 7:ef0ef43d49e7
411 parent: 0:68795b066622
411 parent: 0:68795b066622
412 user: foo
412 user: foo
413 date: Thu Jan 01 00:00:00 1970 +0000
413 date: Thu Jan 01 00:00:00 1970 +0000
414 summary: 2
414 summary: 2
415
415
416 changeset: 8:6b9e5368ca4e
416 changeset: 8:6b9e5368ca4e
417 user: bar
417 user: bar
418 date: Thu Jan 01 00:00:00 1970 +0000
418 date: Thu Jan 01 00:00:00 1970 +0000
419 summary: 1
419 summary: 1
420
420
421 changeset: 9:1905859650ec
421 changeset: 9:1905859650ec
422 user: test
422 user: test
423 date: Thu Jan 01 00:00:00 1970 +0000
423 date: Thu Jan 01 00:00:00 1970 +0000
424 summary: 5
424 summary: 5
425
425
426 changeset: 10:52dc0b4c6907
426 changeset: 10:52dc0b4c6907
427 user: test
427 user: test
428 date: Thu Jan 01 00:00:00 1970 +0000
428 date: Thu Jan 01 00:00:00 1970 +0000
429 summary: 4
429 summary: 4
430
430
431 changeset: 11:882b35362a6b
431 changeset: 11:882b35362a6b
432 user: test
432 user: test
433 date: Thu Jan 01 00:00:00 1970 +0000
433 date: Thu Jan 01 00:00:00 1970 +0000
434 summary: 3
434 summary: 3
435
435
436 changeset: 13:9db0f28fd374
436 changeset: 13:9db0f28fd374
437 user: foo
437 user: foo
438 date: Thu Jan 01 00:00:00 1970 +0000
438 date: Thu Jan 01 00:00:00 1970 +0000
439 summary: 2
439 summary: 2
440
440
441 changeset: 14:f64defefacee
441 changeset: 14:f64defefacee
442 parent: 1:5d205f8b35b6
442 parent: 1:5d205f8b35b6
443 user: foo
443 user: foo
444 date: Thu Jan 01 00:00:00 1970 +0000
444 date: Thu Jan 01 00:00:00 1970 +0000
445 summary: 3
445 summary: 3
446
446
447 changeset: 17:64ecd9071ce8
447 changeset: 17:64ecd9071ce8
448 user: bar
448 user: bar
449 date: Thu Jan 01 00:00:00 1970 +0000
449 date: Thu Jan 01 00:00:00 1970 +0000
450 summary: 1
450 summary: 1
451
451
452 changeset: 19:2e80e1351d6e
452 changeset: 19:2e80e1351d6e
453 user: test
453 user: test
454 date: Thu Jan 01 00:00:00 1970 +0000
454 date: Thu Jan 01 00:00:00 1970 +0000
455 summary: 2
455 summary: 2
456
456
457 changeset: 21:7e61b508e709
457 changeset: 21:7e61b508e709
458 branch: dev
458 branch: dev
459 tag: tip
459 tag: tip
460 user: foo
460 user: foo
461 date: Thu Jan 01 00:00:00 1970 +0000
461 date: Thu Jan 01 00:00:00 1970 +0000
462 summary: 2
462 summary: 2
463
463
464 $ hg log -r 'destination(2)'
464 $ hg log -r 'destination(2)'
465 changeset: 7:ef0ef43d49e7
465 changeset: 7:ef0ef43d49e7
466 parent: 0:68795b066622
466 parent: 0:68795b066622
467 user: foo
467 user: foo
468 date: Thu Jan 01 00:00:00 1970 +0000
468 date: Thu Jan 01 00:00:00 1970 +0000
469 summary: 2
469 summary: 2
470
470
471 changeset: 13:9db0f28fd374
471 changeset: 13:9db0f28fd374
472 user: foo
472 user: foo
473 date: Thu Jan 01 00:00:00 1970 +0000
473 date: Thu Jan 01 00:00:00 1970 +0000
474 summary: 2
474 summary: 2
475
475
476 changeset: 19:2e80e1351d6e
476 changeset: 19:2e80e1351d6e
477 user: test
477 user: test
478 date: Thu Jan 01 00:00:00 1970 +0000
478 date: Thu Jan 01 00:00:00 1970 +0000
479 summary: 2
479 summary: 2
480
480
481 changeset: 21:7e61b508e709
481 changeset: 21:7e61b508e709
482 branch: dev
482 branch: dev
483 tag: tip
483 tag: tip
484 user: foo
484 user: foo
485 date: Thu Jan 01 00:00:00 1970 +0000
485 date: Thu Jan 01 00:00:00 1970 +0000
486 summary: 2
486 summary: 2
487
487
488 Transplants of grafts can find a destination...
488 Transplants of grafts can find a destination...
489 $ hg log -r 'destination(7)'
489 $ hg log -r 'destination(7)'
490 changeset: 21:7e61b508e709
490 changeset: 21:7e61b508e709
491 branch: dev
491 branch: dev
492 tag: tip
492 tag: tip
493 user: foo
493 user: foo
494 date: Thu Jan 01 00:00:00 1970 +0000
494 date: Thu Jan 01 00:00:00 1970 +0000
495 summary: 2
495 summary: 2
496
496
497 ... grafts of grafts unfortunately can't
497 ... grafts of grafts unfortunately can't
498 $ hg graft -q 13
498 $ hg graft -q 13
499 $ hg log -r 'destination(13)'
499 $ hg log -r 'destination(13)'
500 All copies of a cset
500 All copies of a cset
501 $ hg log -r 'origin(13) or destination(origin(13))'
501 $ hg log -r 'origin(13) or destination(origin(13))'
502 changeset: 2:5c095ad7e90f
502 changeset: 2:5c095ad7e90f
503 user: test
503 user: test
504 date: Thu Jan 01 00:00:00 1970 +0000
504 date: Thu Jan 01 00:00:00 1970 +0000
505 summary: 2
505 summary: 2
506
506
507 changeset: 7:ef0ef43d49e7
507 changeset: 7:ef0ef43d49e7
508 parent: 0:68795b066622
508 parent: 0:68795b066622
509 user: foo
509 user: foo
510 date: Thu Jan 01 00:00:00 1970 +0000
510 date: Thu Jan 01 00:00:00 1970 +0000
511 summary: 2
511 summary: 2
512
512
513 changeset: 13:9db0f28fd374
513 changeset: 13:9db0f28fd374
514 user: foo
514 user: foo
515 date: Thu Jan 01 00:00:00 1970 +0000
515 date: Thu Jan 01 00:00:00 1970 +0000
516 summary: 2
516 summary: 2
517
517
518 changeset: 19:2e80e1351d6e
518 changeset: 19:2e80e1351d6e
519 user: test
519 user: test
520 date: Thu Jan 01 00:00:00 1970 +0000
520 date: Thu Jan 01 00:00:00 1970 +0000
521 summary: 2
521 summary: 2
522
522
523 changeset: 21:7e61b508e709
523 changeset: 21:7e61b508e709
524 branch: dev
524 branch: dev
525 user: foo
525 user: foo
526 date: Thu Jan 01 00:00:00 1970 +0000
526 date: Thu Jan 01 00:00:00 1970 +0000
527 summary: 2
527 summary: 2
528
528
529 changeset: 22:1313d0a825e2
529 changeset: 22:1313d0a825e2
530 branch: dev
530 branch: dev
531 tag: tip
531 tag: tip
532 user: foo
532 user: foo
533 date: Thu Jan 01 00:00:00 1970 +0000
533 date: Thu Jan 01 00:00:00 1970 +0000
534 summary: 2
534 summary: 2
535
535
@@ -1,101 +1,101 b''
1 http://mercurial.selenic.com/bts/issue672
1 http://mercurial.selenic.com/bts/issue672
2
2
3 # 0-2-4
3 # 0-2-4
4 # \ \ \
4 # \ \ \
5 # 1-3-5
5 # 1-3-5
6 #
6 #
7 # rename in #1, content change in #4.
7 # rename in #1, content change in #4.
8
8
9 $ hg init
9 $ hg init
10
10
11 $ touch 1
11 $ touch 1
12 $ touch 2
12 $ touch 2
13 $ hg commit -Am init # 0
13 $ hg commit -Am init # 0
14 adding 1
14 adding 1
15 adding 2
15 adding 2
16
16
17 $ hg rename 1 1a
17 $ hg rename 1 1a
18 $ hg commit -m rename # 1
18 $ hg commit -m rename # 1
19
19
20 $ hg co -C 0
20 $ hg co -C 0
21 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
21 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
22
22
23 $ echo unrelated >> 2
23 $ echo unrelated >> 2
24 $ hg ci -m unrelated1 # 2
24 $ hg ci -m unrelated1 # 2
25 created new head
25 created new head
26
26
27 $ hg merge --debug 1
27 $ hg merge --debug 1
28 searching for copies back to rev 1
28 searching for copies back to rev 1
29 unmatched files in other:
29 unmatched files in other:
30 1a
30 1a
31 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
31 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
32 src: '1' -> dst: '1a'
32 src: '1' -> dst: '1a'
33 checking for directory renames
33 checking for directory renames
34 resolving manifests
34 resolving manifests
35 overwrite: False, partial: False
35 overwrite: False, partial: False
36 ancestor: 81f4b099af3d, local: c64f439569a9+, remote: c12dcd37c90a
36 ancestor: 81f4b099af3d, local: c64f439569a9+, remote: c12dcd37c90a
37 1: other deleted -> r
37 1: other deleted -> r
38 1a: remote created -> g
38 1a: remote created -> g
39 updating: 1 1/2 files (50.00%)
39 updating: 1 1/2 files (50.00%)
40 removing 1
40 removing 1
41 updating: 1a 2/2 files (100.00%)
41 updating: 1a 2/2 files (100.00%)
42 getting 1a
42 getting 1a
43 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
43 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
44 (branch merge, don't forget to commit)
44 (branch merge, don't forget to commit)
45
45
46 $ hg ci -m merge1 # 3
46 $ hg ci -m merge1 # 3
47
47
48 $ hg co -C 2
48 $ hg co -C 2
49 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
49 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
50
50
51 $ echo hello >> 1
51 $ echo hello >> 1
52 $ hg ci -m unrelated2 # 4
52 $ hg ci -m unrelated2 # 4
53 created new head
53 created new head
54
54
55 $ hg co -C 3
55 $ hg co -C 3
56 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
56 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
57
57
58 $ hg merge -y --debug 4
58 $ hg merge -y --debug 4
59 searching for copies back to rev 1
59 searching for copies back to rev 1
60 unmatched files in local:
60 unmatched files in local:
61 1a
61 1a
62 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
62 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
63 src: '1' -> dst: '1a' *
63 src: '1' -> dst: '1a' *
64 checking for directory renames
64 checking for directory renames
65 resolving manifests
65 resolving manifests
66 overwrite: False, partial: False
66 overwrite: False, partial: False
67 ancestor: c64f439569a9, local: e327dca35ac8+, remote: 746e9549ea96
67 ancestor: c64f439569a9, local: e327dca35ac8+, remote: 746e9549ea96
68 1a: local copied/moved to 1 -> m
68 1a: local copied/moved to 1 -> m
69 preserving 1a for resolve of 1a
69 preserving 1a for resolve of 1a
70 updating: 1a 1/1 files (100.00%)
70 updating: 1a 1/1 files (100.00%)
71 picked tool 'internal:merge' for 1a (binary False symlink False)
71 picked tool 'internal:merge' for 1a (binary False symlink False)
72 merging 1a and 1 to 1a
72 merging 1a and 1 to 1a
73 my 1a@e327dca35ac8+ other 1@746e9549ea96 ancestor 1@81f4b099af3d
73 my 1a@e327dca35ac8+ other 1@746e9549ea96 ancestor 1@81f4b099af3d
74 premerge successful
74 premerge successful
75 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
75 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
76 (branch merge, don't forget to commit)
76 (branch merge, don't forget to commit)
77
77
78 $ hg co -C 4
78 $ hg co -C 4
79 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
79 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
80
80
81 $ hg merge -y --debug 3
81 $ hg merge -y --debug 3
82 searching for copies back to rev 1
82 searching for copies back to rev 1
83 unmatched files in other:
83 unmatched files in other:
84 1a
84 1a
85 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
85 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
86 src: '1' -> dst: '1a' *
86 src: '1' -> dst: '1a' *
87 checking for directory renames
87 checking for directory renames
88 resolving manifests
88 resolving manifests
89 overwrite: False, partial: False
89 overwrite: False, partial: False
90 ancestor: c64f439569a9, local: 746e9549ea96+, remote: e327dca35ac8
90 ancestor: c64f439569a9, local: 746e9549ea96+, remote: e327dca35ac8
91 1: remote moved to 1a -> m
91 1: remote moved to 1a -> m
92 preserving 1 for resolve of 1a
92 preserving 1 for resolve of 1a
93 removing 1
93 removing 1
94 updating: 1 1/1 files (100.00%)
94 updating: 1 1/1 files (100.00%)
95 picked tool 'internal:merge' for 1a (binary False symlink False)
95 picked tool 'internal:merge' for 1a (binary False symlink False)
96 merging 1 and 1a to 1a
96 merging 1 and 1a to 1a
97 my 1a@746e9549ea96+ other 1a@e327dca35ac8 ancestor 1@81f4b099af3d
97 my 1a@746e9549ea96+ other 1a@e327dca35ac8 ancestor 1@81f4b099af3d
98 premerge successful
98 premerge successful
99 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
99 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
100 (branch merge, don't forget to commit)
100 (branch merge, don't forget to commit)
101
101
@@ -1,184 +1,184 b''
1 Check that renames are correctly saved by a commit after a merge
1 Check that renames are correctly saved by a commit after a merge
2
2
3 Test with the merge on 3 having the rename on the local parent
3 Test with the merge on 3 having the rename on the local parent
4
4
5 $ hg init a
5 $ hg init a
6 $ cd a
6 $ cd a
7
7
8 $ echo line1 > foo
8 $ echo line1 > foo
9 $ hg add foo
9 $ hg add foo
10 $ hg ci -m '0: add foo'
10 $ hg ci -m '0: add foo'
11
11
12 $ echo line2 >> foo
12 $ echo line2 >> foo
13 $ hg ci -m '1: change foo'
13 $ hg ci -m '1: change foo'
14
14
15 $ hg up -C 0
15 $ hg up -C 0
16 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
16 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
17
17
18 $ hg mv foo bar
18 $ hg mv foo bar
19 $ rm bar
19 $ rm bar
20 $ echo line0 > bar
20 $ echo line0 > bar
21 $ echo line1 >> bar
21 $ echo line1 >> bar
22 $ hg ci -m '2: mv foo bar; change bar'
22 $ hg ci -m '2: mv foo bar; change bar'
23 created new head
23 created new head
24
24
25 $ hg merge 1
25 $ hg merge 1
26 merging bar and foo to bar
26 merging bar and foo to bar
27 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
27 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
28 (branch merge, don't forget to commit)
28 (branch merge, don't forget to commit)
29
29
30 $ cat bar
30 $ cat bar
31 line0
31 line0
32 line1
32 line1
33 line2
33 line2
34
34
35 $ hg ci -m '3: merge with local rename'
35 $ hg ci -m '3: merge with local rename'
36
36
37 $ hg debugindex bar
37 $ hg debugindex bar
38 rev offset length ..... linkrev nodeid p1 p2 (re)
38 rev offset length ..... linkrev nodeid p1 p2 (re)
39 0 0 77 ..... 2 d35118874825 000000000000 000000000000 (re)
39 0 0 77 ..... 2 d35118874825 000000000000 000000000000 (re)
40 1 77 76 ..... 3 5345f5ab8abd 000000000000 d35118874825 (re)
40 1 77 76 ..... 3 5345f5ab8abd 000000000000 d35118874825 (re)
41
41
42 $ hg debugrename bar
42 $ hg debugrename bar
43 bar renamed from foo:9e25c27b87571a1edee5ae4dddee5687746cc8e2
43 bar renamed from foo:9e25c27b87571a1edee5ae4dddee5687746cc8e2
44
44
45 $ hg debugindex foo
45 $ hg debugindex foo
46 rev offset length ..... linkrev nodeid p1 p2 (re)
46 rev offset length ..... linkrev nodeid p1 p2 (re)
47 0 0 7 ..... 0 690b295714ae 000000000000 000000000000 (re)
47 0 0 7 ..... 0 690b295714ae 000000000000 000000000000 (re)
48 1 7 13 ..... 1 9e25c27b8757 690b295714ae 000000000000 (re)
48 1 7 13 ..... 1 9e25c27b8757 690b295714ae 000000000000 (re)
49
49
50
50
51 Revert the content change from rev 2:
51 Revert the content change from rev 2:
52
52
53 $ hg up -C 2
53 $ hg up -C 2
54 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
54 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
55 $ rm bar
55 $ rm bar
56 $ echo line1 > bar
56 $ echo line1 > bar
57 $ hg ci -m '4: revert content change from rev 2'
57 $ hg ci -m '4: revert content change from rev 2'
58 created new head
58 created new head
59
59
60 $ hg log --template '{rev}:{node|short} {parents}\n'
60 $ hg log --template '{rev}:{node|short} {parents}\n'
61 4:2263c1be0967 2:0f2ff26688b9
61 4:2263c1be0967 2:0f2ff26688b9
62 3:0555950ead28 2:0f2ff26688b9 1:5cd961e4045d
62 3:0555950ead28 2:0f2ff26688b9 1:5cd961e4045d
63 2:0f2ff26688b9 0:2665aaee66e9
63 2:0f2ff26688b9 0:2665aaee66e9
64 1:5cd961e4045d
64 1:5cd961e4045d
65 0:2665aaee66e9
65 0:2665aaee66e9
66
66
67 This should use bar@rev2 as the ancestor:
67 This should use bar@rev2 as the ancestor:
68
68
69 $ hg --debug merge 3
69 $ hg --debug merge 3
70 searching for copies back to rev 1
70 searching for copies back to rev 1
71 resolving manifests
71 resolving manifests
72 overwrite: False, partial: False
72 overwrite: False, partial: False
73 ancestor: 0f2ff26688b9, local: 2263c1be0967+, remote: 0555950ead28
73 ancestor: 0f2ff26688b9, local: 2263c1be0967+, remote: 0555950ead28
74 bar: versions differ -> m
74 bar: versions differ -> m
75 preserving bar for resolve of bar
75 preserving bar for resolve of bar
76 updating: bar 1/1 files (100.00%)
76 updating: bar 1/1 files (100.00%)
77 picked tool 'internal:merge' for bar (binary False symlink False)
77 picked tool 'internal:merge' for bar (binary False symlink False)
78 merging bar
78 merging bar
79 my bar@2263c1be0967+ other bar@0555950ead28 ancestor bar@0f2ff26688b9
79 my bar@2263c1be0967+ other bar@0555950ead28 ancestor bar@0f2ff26688b9
80 premerge successful
80 premerge successful
81 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
81 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
82 (branch merge, don't forget to commit)
82 (branch merge, don't forget to commit)
83
83
84 $ cat bar
84 $ cat bar
85 line1
85 line1
86 line2
86 line2
87
87
88 $ hg ci -m '5: merge'
88 $ hg ci -m '5: merge'
89
89
90 $ hg debugindex bar
90 $ hg debugindex bar
91 rev offset length ..... linkrev nodeid p1 p2 (re)
91 rev offset length ..... linkrev nodeid p1 p2 (re)
92 0 0 77 ..... 2 d35118874825 000000000000 000000000000 (re)
92 0 0 77 ..... 2 d35118874825 000000000000 000000000000 (re)
93 1 77 76 ..... 3 5345f5ab8abd 000000000000 d35118874825 (re)
93 1 77 76 ..... 3 5345f5ab8abd 000000000000 d35118874825 (re)
94 2 153 7 ..... 4 ff4b45017382 d35118874825 000000000000 (re)
94 2 153 7 ..... 4 ff4b45017382 d35118874825 000000000000 (re)
95 3 160 13 ..... 5 3701b4893544 ff4b45017382 5345f5ab8abd (re)
95 3 160 13 ..... 5 3701b4893544 ff4b45017382 5345f5ab8abd (re)
96
96
97
97
98 Same thing, but with the merge on 3 having the rename
98 Same thing, but with the merge on 3 having the rename
99 on the remote parent:
99 on the remote parent:
100
100
101 $ cd ..
101 $ cd ..
102 $ hg clone -U -r 1 -r 2 a b
102 $ hg clone -U -r 1 -r 2 a b
103 adding changesets
103 adding changesets
104 adding manifests
104 adding manifests
105 adding file changes
105 adding file changes
106 added 3 changesets with 3 changes to 2 files (+1 heads)
106 added 3 changesets with 3 changes to 2 files (+1 heads)
107 $ cd b
107 $ cd b
108
108
109 $ hg up -C 1
109 $ hg up -C 1
110 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
110 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
111
111
112 $ hg merge 2
112 $ hg merge 2
113 merging foo and bar to bar
113 merging foo and bar to bar
114 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
114 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
115 (branch merge, don't forget to commit)
115 (branch merge, don't forget to commit)
116
116
117 $ cat bar
117 $ cat bar
118 line0
118 line0
119 line1
119 line1
120 line2
120 line2
121
121
122 $ hg ci -m '3: merge with remote rename'
122 $ hg ci -m '3: merge with remote rename'
123
123
124 $ hg debugindex bar
124 $ hg debugindex bar
125 rev offset length ..... linkrev nodeid p1 p2 (re)
125 rev offset length ..... linkrev nodeid p1 p2 (re)
126 0 0 77 ..... 2 d35118874825 000000000000 000000000000 (re)
126 0 0 77 ..... 2 d35118874825 000000000000 000000000000 (re)
127 1 77 76 ..... 3 5345f5ab8abd 000000000000 d35118874825 (re)
127 1 77 76 ..... 3 5345f5ab8abd 000000000000 d35118874825 (re)
128
128
129 $ hg debugrename bar
129 $ hg debugrename bar
130 bar renamed from foo:9e25c27b87571a1edee5ae4dddee5687746cc8e2
130 bar renamed from foo:9e25c27b87571a1edee5ae4dddee5687746cc8e2
131
131
132 $ hg debugindex foo
132 $ hg debugindex foo
133 rev offset length ..... linkrev nodeid p1 p2 (re)
133 rev offset length ..... linkrev nodeid p1 p2 (re)
134 0 0 7 ..... 0 690b295714ae 000000000000 000000000000 (re)
134 0 0 7 ..... 0 690b295714ae 000000000000 000000000000 (re)
135 1 7 13 ..... 1 9e25c27b8757 690b295714ae 000000000000 (re)
135 1 7 13 ..... 1 9e25c27b8757 690b295714ae 000000000000 (re)
136
136
137
137
138 Revert the content change from rev 2:
138 Revert the content change from rev 2:
139
139
140 $ hg up -C 2
140 $ hg up -C 2
141 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
141 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
142 $ rm bar
142 $ rm bar
143 $ echo line1 > bar
143 $ echo line1 > bar
144 $ hg ci -m '4: revert content change from rev 2'
144 $ hg ci -m '4: revert content change from rev 2'
145 created new head
145 created new head
146
146
147 $ hg log --template '{rev}:{node|short} {parents}\n'
147 $ hg log --template '{rev}:{node|short} {parents}\n'
148 4:2263c1be0967 2:0f2ff26688b9
148 4:2263c1be0967 2:0f2ff26688b9
149 3:3ffa6b9e35f0 1:5cd961e4045d 2:0f2ff26688b9
149 3:3ffa6b9e35f0 1:5cd961e4045d 2:0f2ff26688b9
150 2:0f2ff26688b9 0:2665aaee66e9
150 2:0f2ff26688b9 0:2665aaee66e9
151 1:5cd961e4045d
151 1:5cd961e4045d
152 0:2665aaee66e9
152 0:2665aaee66e9
153
153
154 This should use bar@rev2 as the ancestor:
154 This should use bar@rev2 as the ancestor:
155
155
156 $ hg --debug merge 3
156 $ hg --debug merge 3
157 searching for copies back to rev 1
157 searching for copies back to rev 1
158 resolving manifests
158 resolving manifests
159 overwrite: False, partial: False
159 overwrite: False, partial: False
160 ancestor: 0f2ff26688b9, local: 2263c1be0967+, remote: 3ffa6b9e35f0
160 ancestor: 0f2ff26688b9, local: 2263c1be0967+, remote: 3ffa6b9e35f0
161 bar: versions differ -> m
161 bar: versions differ -> m
162 preserving bar for resolve of bar
162 preserving bar for resolve of bar
163 updating: bar 1/1 files (100.00%)
163 updating: bar 1/1 files (100.00%)
164 picked tool 'internal:merge' for bar (binary False symlink False)
164 picked tool 'internal:merge' for bar (binary False symlink False)
165 merging bar
165 merging bar
166 my bar@2263c1be0967+ other bar@3ffa6b9e35f0 ancestor bar@0f2ff26688b9
166 my bar@2263c1be0967+ other bar@3ffa6b9e35f0 ancestor bar@0f2ff26688b9
167 premerge successful
167 premerge successful
168 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
168 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
169 (branch merge, don't forget to commit)
169 (branch merge, don't forget to commit)
170
170
171 $ cat bar
171 $ cat bar
172 line1
172 line1
173 line2
173 line2
174
174
175 $ hg ci -m '5: merge'
175 $ hg ci -m '5: merge'
176
176
177 $ hg debugindex bar
177 $ hg debugindex bar
178 rev offset length ..... linkrev nodeid p1 p2 (re)
178 rev offset length ..... linkrev nodeid p1 p2 (re)
179 0 0 77 ..... 2 d35118874825 000000000000 000000000000 (re)
179 0 0 77 ..... 2 d35118874825 000000000000 000000000000 (re)
180 1 77 76 ..... 3 5345f5ab8abd 000000000000 d35118874825 (re)
180 1 77 76 ..... 3 5345f5ab8abd 000000000000 d35118874825 (re)
181 2 153 7 ..... 4 ff4b45017382 d35118874825 000000000000 (re)
181 2 153 7 ..... 4 ff4b45017382 d35118874825 000000000000 (re)
182 3 160 13 ..... 5 3701b4893544 ff4b45017382 5345f5ab8abd (re)
182 3 160 13 ..... 5 3701b4893544 ff4b45017382 5345f5ab8abd (re)
183
183
184 $ cd ..
184 $ cd ..
@@ -1,376 +1,376 b''
1 $ "$TESTDIR/hghave" symlink execbit || exit 80
1 $ "$TESTDIR/hghave" symlink execbit || exit 80
2
2
3 $ tellmeabout() {
3 $ tellmeabout() {
4 > if [ -h $1 ]; then
4 > if [ -h $1 ]; then
5 > echo $1 is a symlink:
5 > echo $1 is a symlink:
6 > $TESTDIR/readlink.py $1
6 > $TESTDIR/readlink.py $1
7 > elif [ -x $1 ]; then
7 > elif [ -x $1 ]; then
8 > echo $1 is an executable file with content:
8 > echo $1 is an executable file with content:
9 > cat $1
9 > cat $1
10 > else
10 > else
11 > echo $1 is a plain file with content:
11 > echo $1 is a plain file with content:
12 > cat $1
12 > cat $1
13 > fi
13 > fi
14 > }
14 > }
15
15
16 $ hg init test1
16 $ hg init test1
17 $ cd test1
17 $ cd test1
18
18
19 $ echo a > a
19 $ echo a > a
20 $ hg ci -Aqmadd
20 $ hg ci -Aqmadd
21 $ chmod +x a
21 $ chmod +x a
22 $ hg ci -mexecutable
22 $ hg ci -mexecutable
23
23
24 $ hg up -q 0
24 $ hg up -q 0
25 $ rm a
25 $ rm a
26 $ ln -s symlink a
26 $ ln -s symlink a
27 $ hg ci -msymlink
27 $ hg ci -msymlink
28 created new head
28 created new head
29
29
30 Symlink is local parent, executable is other:
30 Symlink is local parent, executable is other:
31
31
32 $ hg merge --debug
32 $ hg merge --debug
33 searching for copies back to rev 1
33 searching for copies back to rev 1
34 resolving manifests
34 resolving manifests
35 overwrite: False, partial: False
35 overwrite: False, partial: False
36 ancestor: c334dc3be0da, local: 521a1e40188f+, remote: 3574f3e69b1c
36 ancestor: c334dc3be0da, local: 521a1e40188f+, remote: 3574f3e69b1c
37 a: versions differ -> m
37 a: versions differ -> m
38 preserving a for resolve of a
38 preserving a for resolve of a
39 updating: a 1/1 files (100.00%)
39 updating: a 1/1 files (100.00%)
40 picked tool 'internal:merge' for a (binary False symlink True)
40 picked tool 'internal:merge' for a (binary False symlink True)
41 merging a
41 merging a
42 my a@521a1e40188f+ other a@3574f3e69b1c ancestor a@c334dc3be0da
42 my a@521a1e40188f+ other a@3574f3e69b1c ancestor a@c334dc3be0da
43 warning: internal:merge cannot merge symlinks for a
43 warning: internal:merge cannot merge symlinks for a
44 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
44 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
45 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
45 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
46 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
46 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
47 [1]
47 [1]
48
48
49 $ tellmeabout a
49 $ tellmeabout a
50 a is a symlink:
50 a is a symlink:
51 a -> symlink
51 a -> symlink
52 $ hg resolve a --tool internal:other
52 $ hg resolve a --tool internal:other
53 $ tellmeabout a
53 $ tellmeabout a
54 a is an executable file with content:
54 a is an executable file with content:
55 a
55 a
56 $ hg st
56 $ hg st
57 M a
57 M a
58 ? a.orig
58 ? a.orig
59
59
60 Symlink is other parent, executable is local:
60 Symlink is other parent, executable is local:
61
61
62 $ hg update -C 1
62 $ hg update -C 1
63 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
63 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
64
64
65 $ hg merge --debug
65 $ hg merge --debug
66 searching for copies back to rev 1
66 searching for copies back to rev 1
67 resolving manifests
67 resolving manifests
68 overwrite: False, partial: False
68 overwrite: False, partial: False
69 ancestor: c334dc3be0da, local: 3574f3e69b1c+, remote: 521a1e40188f
69 ancestor: c334dc3be0da, local: 3574f3e69b1c+, remote: 521a1e40188f
70 a: versions differ -> m
70 a: versions differ -> m
71 preserving a for resolve of a
71 preserving a for resolve of a
72 updating: a 1/1 files (100.00%)
72 updating: a 1/1 files (100.00%)
73 picked tool 'internal:merge' for a (binary False symlink True)
73 picked tool 'internal:merge' for a (binary False symlink True)
74 merging a
74 merging a
75 my a@3574f3e69b1c+ other a@521a1e40188f ancestor a@c334dc3be0da
75 my a@3574f3e69b1c+ other a@521a1e40188f ancestor a@c334dc3be0da
76 warning: internal:merge cannot merge symlinks for a
76 warning: internal:merge cannot merge symlinks for a
77 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
77 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
78 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
78 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
79 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
79 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
80 [1]
80 [1]
81
81
82 $ tellmeabout a
82 $ tellmeabout a
83 a is an executable file with content:
83 a is an executable file with content:
84 a
84 a
85
85
86 Update to link without local change should get us a symlink (issue3316):
86 Update to link without local change should get us a symlink (issue3316):
87
87
88 $ hg up -C 0
88 $ hg up -C 0
89 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
89 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
90 $ hg up
90 $ hg up
91 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
91 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
92 $ hg st
92 $ hg st
93 ? a.orig
93 ? a.orig
94
94
95 Update to link with local change should cause a merge prompt (issue3200):
95 Update to link with local change should cause a merge prompt (issue3200):
96
96
97 $ hg up -Cq 0
97 $ hg up -Cq 0
98 $ echo data > a
98 $ echo data > a
99 $ HGMERGE= hg up -y --debug
99 $ HGMERGE= hg up -y --debug
100 searching for copies back to rev 2
100 searching for copies back to rev 2
101 resolving manifests
101 resolving manifests
102 overwrite: False, partial: False
102 overwrite: False, partial: False
103 ancestor: c334dc3be0da, local: c334dc3be0da+, remote: 521a1e40188f
103 ancestor: c334dc3be0da, local: c334dc3be0da+, remote: 521a1e40188f
104 a: versions differ -> m
104 a: versions differ -> m
105 preserving a for resolve of a
105 preserving a for resolve of a
106 updating: a 1/1 files (100.00%)
106 updating: a 1/1 files (100.00%)
107 (couldn't find merge tool hgmerge|tool hgmerge can't handle symlinks) (re)
107 (couldn't find merge tool hgmerge|tool hgmerge can't handle symlinks) (re)
108 picked tool 'internal:prompt' for a (binary False symlink True)
108 picked tool 'internal:prompt' for a (binary False symlink True)
109 no tool found to merge a
109 no tool found to merge a
110 keep (l)ocal or take (o)ther? l
110 keep (l)ocal or take (o)ther? l
111 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
111 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
112 $ hg diff --git
112 $ hg diff --git
113 diff --git a/a b/a
113 diff --git a/a b/a
114 old mode 120000
114 old mode 120000
115 new mode 100644
115 new mode 100644
116 --- a/a
116 --- a/a
117 +++ b/a
117 +++ b/a
118 @@ -1,1 +1,1 @@
118 @@ -1,1 +1,1 @@
119 -symlink
119 -symlink
120 \ No newline at end of file
120 \ No newline at end of file
121 +data
121 +data
122
122
123
123
124 Test only 'l' change - happens rarely, except when recovering from situations
124 Test only 'l' change - happens rarely, except when recovering from situations
125 where that was what happened.
125 where that was what happened.
126
126
127 $ hg init test2
127 $ hg init test2
128 $ cd test2
128 $ cd test2
129 $ printf base > f
129 $ printf base > f
130 $ hg ci -Aqm0
130 $ hg ci -Aqm0
131 $ echo file > f
131 $ echo file > f
132 $ echo content >> f
132 $ echo content >> f
133 $ hg ci -qm1
133 $ hg ci -qm1
134 $ hg up -qr0
134 $ hg up -qr0
135 $ rm f
135 $ rm f
136 $ ln -s base f
136 $ ln -s base f
137 $ hg ci -qm2
137 $ hg ci -qm2
138 $ hg merge
138 $ hg merge
139 merging f
139 merging f
140 warning: internal:merge cannot merge symlinks for f
140 warning: internal:merge cannot merge symlinks for f
141 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
141 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
142 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
142 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
143 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
143 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
144 [1]
144 [1]
145 $ tellmeabout f
145 $ tellmeabout f
146 f is a symlink:
146 f is a symlink:
147 f -> base
147 f -> base
148
148
149 $ hg up -Cqr1
149 $ hg up -Cqr1
150 $ hg merge
150 $ hg merge
151 merging f
151 merging f
152 warning: internal:merge cannot merge symlinks for f
152 warning: internal:merge cannot merge symlinks for f
153 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
153 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
154 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
154 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
155 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
155 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
156 [1]
156 [1]
157 $ tellmeabout f
157 $ tellmeabout f
158 f is a plain file with content:
158 f is a plain file with content:
159 file
159 file
160 content
160 content
161
161
162 $ cd ..
162 $ cd ..
163
163
164 Test removed 'x' flag merged with change to symlink
164 Test removed 'x' flag merged with change to symlink
165
165
166 $ hg init test3
166 $ hg init test3
167 $ cd test3
167 $ cd test3
168 $ echo f > f
168 $ echo f > f
169 $ chmod +x f
169 $ chmod +x f
170 $ hg ci -Aqm0
170 $ hg ci -Aqm0
171 $ chmod -x f
171 $ chmod -x f
172 $ hg ci -qm1
172 $ hg ci -qm1
173 $ hg up -qr0
173 $ hg up -qr0
174 $ rm f
174 $ rm f
175 $ ln -s dangling f
175 $ ln -s dangling f
176 $ hg ci -qm2
176 $ hg ci -qm2
177 $ hg merge
177 $ hg merge
178 merging f
178 merging f
179 warning: internal:merge cannot merge symlinks for f
179 warning: internal:merge cannot merge symlinks for f
180 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
180 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
181 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
181 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
182 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
182 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
183 [1]
183 [1]
184 $ tellmeabout f
184 $ tellmeabout f
185 f is a symlink:
185 f is a symlink:
186 f -> dangling
186 f -> dangling
187
187
188 $ hg up -Cqr1
188 $ hg up -Cqr1
189 $ hg merge
189 $ hg merge
190 merging f
190 merging f
191 warning: internal:merge cannot merge symlinks for f
191 warning: internal:merge cannot merge symlinks for f
192 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
192 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
193 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
193 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
194 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
194 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
195 [1]
195 [1]
196 $ tellmeabout f
196 $ tellmeabout f
197 f is a plain file with content:
197 f is a plain file with content:
198 f
198 f
199
199
200 Test removed 'x' flag merged with content change - both ways
200 Test removed 'x' flag merged with content change - both ways
201
201
202 $ hg up -Cqr0
202 $ hg up -Cqr0
203 $ echo change > f
203 $ echo change > f
204 $ hg ci -qm3
204 $ hg ci -qm3
205 $ hg merge -r1
205 $ hg merge -r1
206 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
206 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
207 (branch merge, don't forget to commit)
207 (branch merge, don't forget to commit)
208 $ tellmeabout f
208 $ tellmeabout f
209 f is a plain file with content:
209 f is a plain file with content:
210 change
210 change
211
211
212 $ hg up -qCr1
212 $ hg up -qCr1
213 $ hg merge -r3
213 $ hg merge -r3
214 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
214 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
215 (branch merge, don't forget to commit)
215 (branch merge, don't forget to commit)
216 $ tellmeabout f
216 $ tellmeabout f
217 f is a plain file with content:
217 f is a plain file with content:
218 change
218 change
219
219
220 $ cd ..
220 $ cd ..
221
221
222 Test merge with no common ancestor:
222 Test merge with no common ancestor:
223 a: just different
223 a: just different
224 b: x vs -, different (cannot calculate x, cannot ask merge tool)
224 b: x vs -, different (cannot calculate x, cannot ask merge tool)
225 c: x vs -, same (cannot calculate x, merge tool is no good)
225 c: x vs -, same (cannot calculate x, merge tool is no good)
226 d: x vs l, different
226 d: x vs l, different
227 e: x vs l, same
227 e: x vs l, same
228 f: - vs l, different
228 f: - vs l, different
229 g: - vs l, same
229 g: - vs l, same
230 h: l vs l, different
230 h: l vs l, different
231 (where same means the filelog entry is shared and there thus is an ancestor!)
231 (where same means the filelog entry is shared and there thus is an ancestor!)
232
232
233 $ hg init test4
233 $ hg init test4
234 $ cd test4
234 $ cd test4
235 $ echo 0 > 0
235 $ echo 0 > 0
236 $ hg ci -Aqm0
236 $ hg ci -Aqm0
237
237
238 $ echo 1 > a
238 $ echo 1 > a
239 $ echo 1 > b
239 $ echo 1 > b
240 $ chmod +x b
240 $ chmod +x b
241 $ echo x > c
241 $ echo x > c
242 $ chmod +x c
242 $ chmod +x c
243 $ echo 1 > d
243 $ echo 1 > d
244 $ chmod +x d
244 $ chmod +x d
245 $ printf x > e
245 $ printf x > e
246 $ chmod +x e
246 $ chmod +x e
247 $ echo 1 > f
247 $ echo 1 > f
248 $ printf x > g
248 $ printf x > g
249 $ ln -s 1 h
249 $ ln -s 1 h
250 $ hg ci -qAm1
250 $ hg ci -qAm1
251
251
252 $ hg up -qr0
252 $ hg up -qr0
253 $ echo 2 > a
253 $ echo 2 > a
254 $ echo 2 > b
254 $ echo 2 > b
255 $ echo x > c
255 $ echo x > c
256 $ ln -s 2 d
256 $ ln -s 2 d
257 $ ln -s x e
257 $ ln -s x e
258 $ ln -s 2 f
258 $ ln -s 2 f
259 $ ln -s x g
259 $ ln -s x g
260 $ ln -s 2 h
260 $ ln -s 2 h
261 $ hg ci -Aqm2
261 $ hg ci -Aqm2
262
262
263 $ hg merge
263 $ hg merge
264 merging a
264 merging a
265 warning: conflicts during merge.
265 warning: conflicts during merge.
266 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
266 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
267 warning: cannot merge flags for b
267 warning: cannot merge flags for b
268 merging b
268 merging b
269 warning: conflicts during merge.
269 warning: conflicts during merge.
270 merging b incomplete! (edit conflicts, then use 'hg resolve --mark')
270 merging b incomplete! (edit conflicts, then use 'hg resolve --mark')
271 merging d
271 merging d
272 warning: internal:merge cannot merge symlinks for d
272 warning: internal:merge cannot merge symlinks for d
273 merging d incomplete! (edit conflicts, then use 'hg resolve --mark')
273 merging d incomplete! (edit conflicts, then use 'hg resolve --mark')
274 merging f
274 merging f
275 warning: internal:merge cannot merge symlinks for f
275 warning: internal:merge cannot merge symlinks for f
276 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
276 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
277 merging h
277 merging h
278 warning: internal:merge cannot merge symlinks for h
278 warning: internal:merge cannot merge symlinks for h
279 merging h incomplete! (edit conflicts, then use 'hg resolve --mark')
279 merging h incomplete! (edit conflicts, then use 'hg resolve --mark')
280 3 files updated, 0 files merged, 0 files removed, 5 files unresolved
280 3 files updated, 0 files merged, 0 files removed, 5 files unresolved
281 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
281 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
282 [1]
282 [1]
283 $ hg resolve -l
283 $ hg resolve -l
284 U a
284 U a
285 U b
285 U b
286 U d
286 U d
287 U f
287 U f
288 U h
288 U h
289 $ tellmeabout a
289 $ tellmeabout a
290 a is a plain file with content:
290 a is a plain file with content:
291 <<<<<<< local
291 <<<<<<< local
292 2
292 2
293 =======
293 =======
294 1
294 1
295 >>>>>>> other
295 >>>>>>> other
296 $ tellmeabout b
296 $ tellmeabout b
297 b is a plain file with content:
297 b is a plain file with content:
298 <<<<<<< local
298 <<<<<<< local
299 2
299 2
300 =======
300 =======
301 1
301 1
302 >>>>>>> other
302 >>>>>>> other
303 $ tellmeabout c
303 $ tellmeabout c
304 c is a plain file with content:
304 c is a plain file with content:
305 x
305 x
306 $ tellmeabout d
306 $ tellmeabout d
307 d is a symlink:
307 d is a symlink:
308 d -> 2
308 d -> 2
309 $ tellmeabout e
309 $ tellmeabout e
310 e is a symlink:
310 e is a symlink:
311 e -> x
311 e -> x
312 $ tellmeabout f
312 $ tellmeabout f
313 f is a symlink:
313 f is a symlink:
314 f -> 2
314 f -> 2
315 $ tellmeabout g
315 $ tellmeabout g
316 g is a symlink:
316 g is a symlink:
317 g -> x
317 g -> x
318 $ tellmeabout h
318 $ tellmeabout h
319 h is a symlink:
319 h is a symlink:
320 h -> 2
320 h -> 2
321
321
322 $ hg up -Cqr1
322 $ hg up -Cqr1
323 $ hg merge
323 $ hg merge
324 merging a
324 merging a
325 warning: conflicts during merge.
325 warning: conflicts during merge.
326 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
326 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
327 warning: cannot merge flags for b
327 warning: cannot merge flags for b
328 merging b
328 merging b
329 warning: conflicts during merge.
329 warning: conflicts during merge.
330 merging b incomplete! (edit conflicts, then use 'hg resolve --mark')
330 merging b incomplete! (edit conflicts, then use 'hg resolve --mark')
331 merging d
331 merging d
332 warning: internal:merge cannot merge symlinks for d
332 warning: internal:merge cannot merge symlinks for d
333 merging d incomplete! (edit conflicts, then use 'hg resolve --mark')
333 merging d incomplete! (edit conflicts, then use 'hg resolve --mark')
334 merging f
334 merging f
335 warning: internal:merge cannot merge symlinks for f
335 warning: internal:merge cannot merge symlinks for f
336 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
336 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
337 merging h
337 merging h
338 warning: internal:merge cannot merge symlinks for h
338 warning: internal:merge cannot merge symlinks for h
339 merging h incomplete! (edit conflicts, then use 'hg resolve --mark')
339 merging h incomplete! (edit conflicts, then use 'hg resolve --mark')
340 3 files updated, 0 files merged, 0 files removed, 5 files unresolved
340 3 files updated, 0 files merged, 0 files removed, 5 files unresolved
341 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
341 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
342 [1]
342 [1]
343 $ tellmeabout a
343 $ tellmeabout a
344 a is a plain file with content:
344 a is a plain file with content:
345 <<<<<<< local
345 <<<<<<< local
346 1
346 1
347 =======
347 =======
348 2
348 2
349 >>>>>>> other
349 >>>>>>> other
350 $ tellmeabout b
350 $ tellmeabout b
351 b is an executable file with content:
351 b is an executable file with content:
352 <<<<<<< local
352 <<<<<<< local
353 1
353 1
354 =======
354 =======
355 2
355 2
356 >>>>>>> other
356 >>>>>>> other
357 $ tellmeabout c
357 $ tellmeabout c
358 c is a plain file with content:
358 c is a plain file with content:
359 x
359 x
360 $ tellmeabout d
360 $ tellmeabout d
361 d is an executable file with content:
361 d is an executable file with content:
362 1
362 1
363 $ tellmeabout e
363 $ tellmeabout e
364 e is an executable file with content:
364 e is an executable file with content:
365 x (no-eol)
365 x (no-eol)
366 $ tellmeabout f
366 $ tellmeabout f
367 f is a plain file with content:
367 f is a plain file with content:
368 1
368 1
369 $ tellmeabout g
369 $ tellmeabout g
370 g is a plain file with content:
370 g is a plain file with content:
371 x (no-eol)
371 x (no-eol)
372 $ tellmeabout h
372 $ tellmeabout h
373 h is a symlink:
373 h is a symlink:
374 h -> 1
374 h -> 1
375
375
376 $ cd ..
376 $ cd ..
@@ -1,147 +1,147 b''
1 initial
1 initial
2 $ hg init test-a
2 $ hg init test-a
3 $ cd test-a
3 $ cd test-a
4 $ cat >test.txt <<"EOF"
4 $ cat >test.txt <<"EOF"
5 > 1
5 > 1
6 > 2
6 > 2
7 > 3
7 > 3
8 > EOF
8 > EOF
9 $ hg add test.txt
9 $ hg add test.txt
10 $ hg commit -m "Initial"
10 $ hg commit -m "Initial"
11
11
12 clone
12 clone
13 $ cd ..
13 $ cd ..
14 $ hg clone test-a test-b
14 $ hg clone test-a test-b
15 updating to branch default
15 updating to branch default
16 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
16 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
17
17
18 change test-a
18 change test-a
19 $ cd test-a
19 $ cd test-a
20 $ cat >test.txt <<"EOF"
20 $ cat >test.txt <<"EOF"
21 > one
21 > one
22 > two
22 > two
23 > three
23 > three
24 > EOF
24 > EOF
25 $ hg commit -m "Numbers as words"
25 $ hg commit -m "Numbers as words"
26
26
27 change test-b
27 change test-b
28 $ cd ../test-b
28 $ cd ../test-b
29 $ cat >test.txt <<"EOF"
29 $ cat >test.txt <<"EOF"
30 > 1
30 > 1
31 > 2.5
31 > 2.5
32 > 3
32 > 3
33 > EOF
33 > EOF
34 $ hg commit -m "2 -> 2.5"
34 $ hg commit -m "2 -> 2.5"
35
35
36 now pull and merge from test-a
36 now pull and merge from test-a
37 $ hg pull ../test-a
37 $ hg pull ../test-a
38 pulling from ../test-a
38 pulling from ../test-a
39 searching for changes
39 searching for changes
40 adding changesets
40 adding changesets
41 adding manifests
41 adding manifests
42 adding file changes
42 adding file changes
43 added 1 changesets with 1 changes to 1 files (+1 heads)
43 added 1 changesets with 1 changes to 1 files (+1 heads)
44 (run 'hg heads' to see heads, 'hg merge' to merge)
44 (run 'hg heads' to see heads, 'hg merge' to merge)
45 $ hg merge
45 $ hg merge
46 merging test.txt
46 merging test.txt
47 warning: conflicts during merge.
47 warning: conflicts during merge.
48 merging test.txt incomplete! (edit conflicts, then use 'hg resolve --mark')
48 merging test.txt incomplete! (edit conflicts, then use 'hg resolve --mark')
49 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
49 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
50 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
50 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
51 [1]
51 [1]
52 resolve conflict
52 resolve conflict
53 $ cat >test.txt <<"EOF"
53 $ cat >test.txt <<"EOF"
54 > one
54 > one
55 > two-point-five
55 > two-point-five
56 > three
56 > three
57 > EOF
57 > EOF
58 $ rm -f *.orig
58 $ rm -f *.orig
59 $ hg resolve -m test.txt
59 $ hg resolve -m test.txt
60 $ hg commit -m "Merge 1"
60 $ hg commit -m "Merge 1"
61
61
62 change test-a again
62 change test-a again
63 $ cd ../test-a
63 $ cd ../test-a
64 $ cat >test.txt <<"EOF"
64 $ cat >test.txt <<"EOF"
65 > one
65 > one
66 > two-point-one
66 > two-point-one
67 > three
67 > three
68 > EOF
68 > EOF
69 $ hg commit -m "two -> two-point-one"
69 $ hg commit -m "two -> two-point-one"
70
70
71 pull and merge from test-a again
71 pull and merge from test-a again
72 $ cd ../test-b
72 $ cd ../test-b
73 $ hg pull ../test-a
73 $ hg pull ../test-a
74 pulling from ../test-a
74 pulling from ../test-a
75 searching for changes
75 searching for changes
76 adding changesets
76 adding changesets
77 adding manifests
77 adding manifests
78 adding file changes
78 adding file changes
79 added 1 changesets with 1 changes to 1 files (+1 heads)
79 added 1 changesets with 1 changes to 1 files (+1 heads)
80 (run 'hg heads' to see heads, 'hg merge' to merge)
80 (run 'hg heads' to see heads, 'hg merge' to merge)
81 $ hg merge --debug
81 $ hg merge --debug
82 searching for copies back to rev 1
82 searching for copies back to rev 1
83 resolving manifests
83 resolving manifests
84 overwrite: False, partial: False
84 overwrite: False, partial: False
85 ancestor: 96b70246a118, local: 50c3a7e29886+, remote: 40d11a4173a8
85 ancestor: 96b70246a118, local: 50c3a7e29886+, remote: 40d11a4173a8
86 test.txt: versions differ -> m
86 test.txt: versions differ -> m
87 preserving test.txt for resolve of test.txt
87 preserving test.txt for resolve of test.txt
88 updating: test.txt 1/1 files (100.00%)
88 updating: test.txt 1/1 files (100.00%)
89 picked tool 'internal:merge' for test.txt (binary False symlink False)
89 picked tool 'internal:merge' for test.txt (binary False symlink False)
90 merging test.txt
90 merging test.txt
91 my test.txt@50c3a7e29886+ other test.txt@40d11a4173a8 ancestor test.txt@96b70246a118
91 my test.txt@50c3a7e29886+ other test.txt@40d11a4173a8 ancestor test.txt@96b70246a118
92 warning: conflicts during merge.
92 warning: conflicts during merge.
93 merging test.txt incomplete! (edit conflicts, then use 'hg resolve --mark')
93 merging test.txt incomplete! (edit conflicts, then use 'hg resolve --mark')
94 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
94 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
95 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
95 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
96 [1]
96 [1]
97
97
98 $ cat test.txt
98 $ cat test.txt
99 one
99 one
100 <<<<<<< local
100 <<<<<<< local
101 two-point-five
101 two-point-five
102 =======
102 =======
103 two-point-one
103 two-point-one
104 >>>>>>> other
104 >>>>>>> other
105 three
105 three
106
106
107 $ hg debugindex test.txt
107 $ hg debugindex test.txt
108 rev offset length ..... linkrev nodeid p1 p2 (re)
108 rev offset length ..... linkrev nodeid p1 p2 (re)
109 0 0 7 ..... 0 01365c4cca56 000000000000 000000000000 (re)
109 0 0 7 ..... 0 01365c4cca56 000000000000 000000000000 (re)
110 1 7 9 ..... 1 7b013192566a 01365c4cca56 000000000000 (re)
110 1 7 9 ..... 1 7b013192566a 01365c4cca56 000000000000 (re)
111 2 16 15 ..... 2 8fe46a3eb557 01365c4cca56 000000000000 (re)
111 2 16 15 ..... 2 8fe46a3eb557 01365c4cca56 000000000000 (re)
112 3 31 2. ..... 3 fc3148072371 7b013192566a 8fe46a3eb557 (re)
112 3 31 2. ..... 3 fc3148072371 7b013192566a 8fe46a3eb557 (re)
113 4 5. 25 ..... 4 d40249267ae3 8fe46a3eb557 000000000000 (re)
113 4 5. 25 ..... 4 d40249267ae3 8fe46a3eb557 000000000000 (re)
114
114
115 $ hg log
115 $ hg log
116 changeset: 4:40d11a4173a8
116 changeset: 4:40d11a4173a8
117 tag: tip
117 tag: tip
118 parent: 2:96b70246a118
118 parent: 2:96b70246a118
119 user: test
119 user: test
120 date: Thu Jan 01 00:00:00 1970 +0000
120 date: Thu Jan 01 00:00:00 1970 +0000
121 summary: two -> two-point-one
121 summary: two -> two-point-one
122
122
123 changeset: 3:50c3a7e29886
123 changeset: 3:50c3a7e29886
124 parent: 1:d1e159716d41
124 parent: 1:d1e159716d41
125 parent: 2:96b70246a118
125 parent: 2:96b70246a118
126 user: test
126 user: test
127 date: Thu Jan 01 00:00:00 1970 +0000
127 date: Thu Jan 01 00:00:00 1970 +0000
128 summary: Merge 1
128 summary: Merge 1
129
129
130 changeset: 2:96b70246a118
130 changeset: 2:96b70246a118
131 parent: 0:b1832b9d912a
131 parent: 0:b1832b9d912a
132 user: test
132 user: test
133 date: Thu Jan 01 00:00:00 1970 +0000
133 date: Thu Jan 01 00:00:00 1970 +0000
134 summary: Numbers as words
134 summary: Numbers as words
135
135
136 changeset: 1:d1e159716d41
136 changeset: 1:d1e159716d41
137 user: test
137 user: test
138 date: Thu Jan 01 00:00:00 1970 +0000
138 date: Thu Jan 01 00:00:00 1970 +0000
139 summary: 2 -> 2.5
139 summary: 2 -> 2.5
140
140
141 changeset: 0:b1832b9d912a
141 changeset: 0:b1832b9d912a
142 user: test
142 user: test
143 date: Thu Jan 01 00:00:00 1970 +0000
143 date: Thu Jan 01 00:00:00 1970 +0000
144 summary: Initial
144 summary: Initial
145
145
146
146
147 $ cd ..
147 $ cd ..
@@ -1,195 +1,195 b''
1 $ hg init
1 $ hg init
2
2
3 $ echo "[merge]" >> .hg/hgrc
3 $ echo "[merge]" >> .hg/hgrc
4 $ echo "followcopies = 1" >> .hg/hgrc
4 $ echo "followcopies = 1" >> .hg/hgrc
5
5
6 $ echo foo > a
6 $ echo foo > a
7 $ echo foo > a2
7 $ echo foo > a2
8 $ hg add a a2
8 $ hg add a a2
9 $ hg ci -m "start"
9 $ hg ci -m "start"
10
10
11 $ hg mv a b
11 $ hg mv a b
12 $ hg mv a2 b2
12 $ hg mv a2 b2
13 $ hg ci -m "rename"
13 $ hg ci -m "rename"
14
14
15 $ hg co 0
15 $ hg co 0
16 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
16 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
17
17
18 $ echo blahblah > a
18 $ echo blahblah > a
19 $ echo blahblah > a2
19 $ echo blahblah > a2
20 $ hg mv a2 c2
20 $ hg mv a2 c2
21 $ hg ci -m "modify"
21 $ hg ci -m "modify"
22 created new head
22 created new head
23
23
24 $ hg merge -y --debug
24 $ hg merge -y --debug
25 searching for copies back to rev 1
25 searching for copies back to rev 1
26 unmatched files in local:
26 unmatched files in local:
27 c2
27 c2
28 unmatched files in other:
28 unmatched files in other:
29 b
29 b
30 b2
30 b2
31 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
31 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
32 src: 'a' -> dst: 'b' *
32 src: 'a' -> dst: 'b' *
33 src: 'a2' -> dst: 'b2' !
33 src: 'a2' -> dst: 'b2' !
34 src: 'a2' -> dst: 'c2' !
34 src: 'a2' -> dst: 'c2' !
35 checking for directory renames
35 checking for directory renames
36 a2: divergent renames -> dr
37 resolving manifests
36 resolving manifests
38 overwrite: False, partial: False
37 overwrite: False, partial: False
39 ancestor: af1939970a1c, local: 044f8520aeeb+, remote: 85c198ef2f6c
38 ancestor: af1939970a1c, local: 044f8520aeeb+, remote: 85c198ef2f6c
40 a: remote moved to b -> m
39 a: remote moved to b -> m
40 preserving a for resolve of b
41 a2: divergent renames -> dr
41 b2: remote created -> g
42 b2: remote created -> g
42 preserving a for resolve of b
43 removing a
43 removing a
44 updating: a 1/3 files (33.33%)
44 updating: a 1/3 files (33.33%)
45 picked tool 'internal:merge' for b (binary False symlink False)
45 picked tool 'internal:merge' for b (binary False symlink False)
46 merging a and b to b
46 merging a and b to b
47 my b@044f8520aeeb+ other b@85c198ef2f6c ancestor a@af1939970a1c
47 my b@044f8520aeeb+ other b@85c198ef2f6c ancestor a@af1939970a1c
48 premerge successful
48 premerge successful
49 updating: a2 2/3 files (66.67%)
49 updating: a2 2/3 files (66.67%)
50 note: possible conflict - a2 was renamed multiple times to:
50 note: possible conflict - a2 was renamed multiple times to:
51 c2
51 c2
52 b2
52 b2
53 updating: b2 3/3 files (100.00%)
53 updating: b2 3/3 files (100.00%)
54 getting b2
54 getting b2
55 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
55 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
56 (branch merge, don't forget to commit)
56 (branch merge, don't forget to commit)
57
57
58 $ hg status -AC
58 $ hg status -AC
59 M b
59 M b
60 a
60 a
61 M b2
61 M b2
62 R a
62 R a
63 C c2
63 C c2
64
64
65 $ cat b
65 $ cat b
66 blahblah
66 blahblah
67
67
68 $ hg ci -m "merge"
68 $ hg ci -m "merge"
69
69
70 $ hg debugindex b
70 $ hg debugindex b
71 rev offset length ..... linkrev nodeid p1 p2 (re)
71 rev offset length ..... linkrev nodeid p1 p2 (re)
72 0 0 67 ..... 1 57eacc201a7f 000000000000 000000000000 (re)
72 0 0 67 ..... 1 57eacc201a7f 000000000000 000000000000 (re)
73 1 67 72 ..... 3 4727ba907962 000000000000 57eacc201a7f (re)
73 1 67 72 ..... 3 4727ba907962 000000000000 57eacc201a7f (re)
74
74
75 $ hg debugrename b
75 $ hg debugrename b
76 b renamed from a:dd03b83622e78778b403775d0d074b9ac7387a66
76 b renamed from a:dd03b83622e78778b403775d0d074b9ac7387a66
77
77
78 This used to trigger a "divergent renames" warning, despite no renames
78 This used to trigger a "divergent renames" warning, despite no renames
79
79
80 $ hg cp b b3
80 $ hg cp b b3
81 $ hg cp b b4
81 $ hg cp b b4
82 $ hg ci -A -m 'copy b twice'
82 $ hg ci -A -m 'copy b twice'
83 $ hg up eb92d88a9712
83 $ hg up eb92d88a9712
84 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
84 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
85 $ hg up
85 $ hg up
86 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
86 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
87 $ hg rm b3 b4
87 $ hg rm b3 b4
88 $ hg ci -m 'clean up a bit of our mess'
88 $ hg ci -m 'clean up a bit of our mess'
89
89
90 We'd rather not warn on divergent renames done in the same changeset (issue2113)
90 We'd rather not warn on divergent renames done in the same changeset (issue2113)
91
91
92 $ hg cp b b3
92 $ hg cp b b3
93 $ hg mv b b4
93 $ hg mv b b4
94 $ hg ci -A -m 'divergent renames in same changeset'
94 $ hg ci -A -m 'divergent renames in same changeset'
95 $ hg up c761c6948de0
95 $ hg up c761c6948de0
96 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
96 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
97 $ hg up
97 $ hg up
98 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
98 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
99
99
100 Check for issue2642
100 Check for issue2642
101
101
102 $ hg init t
102 $ hg init t
103 $ cd t
103 $ cd t
104
104
105 $ echo c0 > f1
105 $ echo c0 > f1
106 $ hg ci -Aqm0
106 $ hg ci -Aqm0
107
107
108 $ hg up null -q
108 $ hg up null -q
109 $ echo c1 > f1 # backport
109 $ echo c1 > f1 # backport
110 $ hg ci -Aqm1
110 $ hg ci -Aqm1
111 $ hg mv f1 f2
111 $ hg mv f1 f2
112 $ hg ci -qm2
112 $ hg ci -qm2
113
113
114 $ hg up 0 -q
114 $ hg up 0 -q
115 $ hg merge 1 -q --tool internal:local
115 $ hg merge 1 -q --tool internal:local
116 $ hg ci -qm3
116 $ hg ci -qm3
117
117
118 $ hg merge 2
118 $ hg merge 2
119 merging f1 and f2 to f2
119 merging f1 and f2 to f2
120 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
120 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
121 (branch merge, don't forget to commit)
121 (branch merge, don't forget to commit)
122
122
123 $ cat f2
123 $ cat f2
124 c0
124 c0
125
125
126 $ cd ..
126 $ cd ..
127
127
128 Check for issue2089
128 Check for issue2089
129
129
130 $ hg init repo2089
130 $ hg init repo2089
131 $ cd repo2089
131 $ cd repo2089
132
132
133 $ echo c0 > f1
133 $ echo c0 > f1
134 $ hg ci -Aqm0
134 $ hg ci -Aqm0
135
135
136 $ hg up null -q
136 $ hg up null -q
137 $ echo c1 > f1
137 $ echo c1 > f1
138 $ hg ci -Aqm1
138 $ hg ci -Aqm1
139
139
140 $ hg up 0 -q
140 $ hg up 0 -q
141 $ hg merge 1 -q --tool internal:local
141 $ hg merge 1 -q --tool internal:local
142 $ echo c2 > f1
142 $ echo c2 > f1
143 $ hg ci -qm2
143 $ hg ci -qm2
144
144
145 $ hg up 1 -q
145 $ hg up 1 -q
146 $ hg mv f1 f2
146 $ hg mv f1 f2
147 $ hg ci -Aqm3
147 $ hg ci -Aqm3
148
148
149 $ hg up 2 -q
149 $ hg up 2 -q
150 $ hg merge 3
150 $ hg merge 3
151 merging f1 and f2 to f2
151 merging f1 and f2 to f2
152 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
152 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
153 (branch merge, don't forget to commit)
153 (branch merge, don't forget to commit)
154
154
155 $ cat f2
155 $ cat f2
156 c2
156 c2
157
157
158 $ cd ..
158 $ cd ..
159
159
160 Check for issue3074
160 Check for issue3074
161
161
162 $ hg init repo3074
162 $ hg init repo3074
163 $ cd repo3074
163 $ cd repo3074
164 $ echo foo > file
164 $ echo foo > file
165 $ hg add file
165 $ hg add file
166 $ hg commit -m "added file"
166 $ hg commit -m "added file"
167 $ hg mv file newfile
167 $ hg mv file newfile
168 $ hg commit -m "renamed file"
168 $ hg commit -m "renamed file"
169 $ hg update 0
169 $ hg update 0
170 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
170 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
171 $ hg rm file
171 $ hg rm file
172 $ hg commit -m "deleted file"
172 $ hg commit -m "deleted file"
173 created new head
173 created new head
174 $ hg merge --debug
174 $ hg merge --debug
175 searching for copies back to rev 1
175 searching for copies back to rev 1
176 unmatched files in other:
176 unmatched files in other:
177 newfile
177 newfile
178 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
178 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
179 src: 'file' -> dst: 'newfile' %
179 src: 'file' -> dst: 'newfile' %
180 checking for directory renames
180 checking for directory renames
181 file: rename and delete -> rd
182 resolving manifests
181 resolving manifests
183 overwrite: False, partial: False
182 overwrite: False, partial: False
184 ancestor: 19d7f95df299, local: 0084274f6b67+, remote: 5d32493049f0
183 ancestor: 19d7f95df299, local: 0084274f6b67+, remote: 5d32493049f0
184 file: rename and delete -> rd
185 newfile: remote created -> g
185 newfile: remote created -> g
186 updating: file 1/2 files (50.00%)
186 updating: file 1/2 files (50.00%)
187 note: possible conflict - file was deleted and renamed to:
187 note: possible conflict - file was deleted and renamed to:
188 newfile
188 newfile
189 updating: newfile 2/2 files (100.00%)
189 updating: newfile 2/2 files (100.00%)
190 getting newfile
190 getting newfile
191 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
191 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
192 (branch merge, don't forget to commit)
192 (branch merge, don't forget to commit)
193 $ hg status
193 $ hg status
194 M newfile
194 M newfile
195 $ cd ..
195 $ cd ..
@@ -1,754 +1,754 b''
1
1
2 $ mkdir -p t
2 $ mkdir -p t
3 $ cd t
3 $ cd t
4 $ cat <<EOF > merge
4 $ cat <<EOF > merge
5 > import sys, os
5 > import sys, os
6 > f = open(sys.argv[1], "wb")
6 > f = open(sys.argv[1], "wb")
7 > f.write("merge %s %s %s" % (sys.argv[1], sys.argv[2], sys.argv[3]))
7 > f.write("merge %s %s %s" % (sys.argv[1], sys.argv[2], sys.argv[3]))
8 > f.close()
8 > f.close()
9 > EOF
9 > EOF
10
10
11 perform a test merge with possible renaming
11 perform a test merge with possible renaming
12 args:
12 args:
13 $1 = action in local branch
13 $1 = action in local branch
14 $2 = action in remote branch
14 $2 = action in remote branch
15 $3 = action in working dir
15 $3 = action in working dir
16 $4 = expected result
16 $4 = expected result
17
17
18 $ tm()
18 $ tm()
19 > {
19 > {
20 > hg init t
20 > hg init t
21 > cd t
21 > cd t
22 > echo "[merge]" >> .hg/hgrc
22 > echo "[merge]" >> .hg/hgrc
23 > echo "followcopies = 1" >> .hg/hgrc
23 > echo "followcopies = 1" >> .hg/hgrc
24 >
24 >
25 > # base
25 > # base
26 > echo base > a
26 > echo base > a
27 > echo base > rev # used to force commits
27 > echo base > rev # used to force commits
28 > hg add a rev
28 > hg add a rev
29 > hg ci -m "base"
29 > hg ci -m "base"
30 >
30 >
31 > # remote
31 > # remote
32 > echo remote > rev
32 > echo remote > rev
33 > if [ "$2" != "" ] ; then $2 ; fi
33 > if [ "$2" != "" ] ; then $2 ; fi
34 > hg ci -m "remote"
34 > hg ci -m "remote"
35 >
35 >
36 > # local
36 > # local
37 > hg co -q 0
37 > hg co -q 0
38 > echo local > rev
38 > echo local > rev
39 > if [ "$1" != "" ] ; then $1 ; fi
39 > if [ "$1" != "" ] ; then $1 ; fi
40 > hg ci -m "local"
40 > hg ci -m "local"
41 >
41 >
42 > # working dir
42 > # working dir
43 > echo local > rev
43 > echo local > rev
44 > if [ "$3" != "" ] ; then $3 ; fi
44 > if [ "$3" != "" ] ; then $3 ; fi
45 >
45 >
46 > # merge
46 > # merge
47 > echo "--------------"
47 > echo "--------------"
48 > echo "test L:$1 R:$2 W:$3 - $4"
48 > echo "test L:$1 R:$2 W:$3 - $4"
49 > echo "--------------"
49 > echo "--------------"
50 > hg merge -y --debug --traceback --tool="python ../merge"
50 > hg merge -y --debug --traceback --tool="python ../merge"
51 >
51 >
52 > echo "--------------"
52 > echo "--------------"
53 > hg status -camC -X rev
53 > hg status -camC -X rev
54 >
54 >
55 > hg ci -m "merge"
55 > hg ci -m "merge"
56 >
56 >
57 > echo "--------------"
57 > echo "--------------"
58 > echo
58 > echo
59 >
59 >
60 > cd ..
60 > cd ..
61 > rm -r t
61 > rm -r t
62 > }
62 > }
63 $ up() {
63 $ up() {
64 > cp rev $1
64 > cp rev $1
65 > hg add $1 2> /dev/null
65 > hg add $1 2> /dev/null
66 > if [ "$2" != "" ] ; then
66 > if [ "$2" != "" ] ; then
67 > cp rev $2
67 > cp rev $2
68 > hg add $2 2> /dev/null
68 > hg add $2 2> /dev/null
69 > fi
69 > fi
70 > }
70 > }
71 $ uc() { up $1; hg cp $1 $2; } # update + copy
71 $ uc() { up $1; hg cp $1 $2; } # update + copy
72 $ um() { up $1; hg mv $1 $2; }
72 $ um() { up $1; hg mv $1 $2; }
73 $ nc() { hg cp $1 $2; } # just copy
73 $ nc() { hg cp $1 $2; } # just copy
74 $ nm() { hg mv $1 $2; } # just move
74 $ nm() { hg mv $1 $2; } # just move
75 $ tm "up a " "nc a b" " " "1 get local a to b"
75 $ tm "up a " "nc a b" " " "1 get local a to b"
76 created new head
76 created new head
77 --------------
77 --------------
78 test L:up a R:nc a b W: - 1 get local a to b
78 test L:up a R:nc a b W: - 1 get local a to b
79 --------------
79 --------------
80 searching for copies back to rev 1
80 searching for copies back to rev 1
81 unmatched files in other:
81 unmatched files in other:
82 b
82 b
83 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
83 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
84 src: 'a' -> dst: 'b' *
84 src: 'a' -> dst: 'b' *
85 checking for directory renames
85 checking for directory renames
86 resolving manifests
86 resolving manifests
87 overwrite: False, partial: False
87 overwrite: False, partial: False
88 ancestor: 924404dff337, local: e300d1c794ec+, remote: 4ce40f5aca24
88 ancestor: 924404dff337, local: e300d1c794ec+, remote: 4ce40f5aca24
89 a: remote copied to b -> m
90 preserving a for resolve of b
89 rev: versions differ -> m
91 rev: versions differ -> m
90 a: remote copied to b -> m
92 preserving rev for resolve of rev
91 preserving a for resolve of b
92 preserving rev for resolve of rev
93 updating: a 1/2 files (50.00%)
93 updating: a 1/2 files (50.00%)
94 picked tool 'python ../merge' for b (binary False symlink False)
94 picked tool 'python ../merge' for b (binary False symlink False)
95 merging a and b to b
95 merging a and b to b
96 my b@e300d1c794ec+ other b@4ce40f5aca24 ancestor a@924404dff337
96 my b@e300d1c794ec+ other b@4ce40f5aca24 ancestor a@924404dff337
97 premerge successful
97 premerge successful
98 updating: rev 2/2 files (100.00%)
98 updating: rev 2/2 files (100.00%)
99 picked tool 'python ../merge' for rev (binary False symlink False)
99 picked tool 'python ../merge' for rev (binary False symlink False)
100 merging rev
100 merging rev
101 my rev@e300d1c794ec+ other rev@4ce40f5aca24 ancestor rev@924404dff337
101 my rev@e300d1c794ec+ other rev@4ce40f5aca24 ancestor rev@924404dff337
102 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
102 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
103 (branch merge, don't forget to commit)
103 (branch merge, don't forget to commit)
104 --------------
104 --------------
105 M b
105 M b
106 a
106 a
107 C a
107 C a
108 --------------
108 --------------
109
109
110 $ tm "nc a b" "up a " " " "2 get rem change to a and b"
110 $ tm "nc a b" "up a " " " "2 get rem change to a and b"
111 created new head
111 created new head
112 --------------
112 --------------
113 test L:nc a b R:up a W: - 2 get rem change to a and b
113 test L:nc a b R:up a W: - 2 get rem change to a and b
114 --------------
114 --------------
115 searching for copies back to rev 1
115 searching for copies back to rev 1
116 unmatched files in local:
116 unmatched files in local:
117 b
117 b
118 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
118 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
119 src: 'a' -> dst: 'b' *
119 src: 'a' -> dst: 'b' *
120 checking for directory renames
120 checking for directory renames
121 resolving manifests
121 resolving manifests
122 overwrite: False, partial: False
122 overwrite: False, partial: False
123 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: f4db7e329e71
123 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: f4db7e329e71
124 a: remote is newer -> g
124 a: remote is newer -> g
125 b: local copied/moved to a -> m
125 b: local copied/moved to a -> m
126 preserving b for resolve of b
126 rev: versions differ -> m
127 rev: versions differ -> m
127 preserving b for resolve of b
128 preserving rev for resolve of rev
128 preserving rev for resolve of rev
129 updating: a 1/3 files (33.33%)
129 updating: a 1/3 files (33.33%)
130 getting a
130 getting a
131 updating: b 2/3 files (66.67%)
131 updating: b 2/3 files (66.67%)
132 picked tool 'python ../merge' for b (binary False symlink False)
132 picked tool 'python ../merge' for b (binary False symlink False)
133 merging b and a to b
133 merging b and a to b
134 my b@86a2aa42fc76+ other a@f4db7e329e71 ancestor a@924404dff337
134 my b@86a2aa42fc76+ other a@f4db7e329e71 ancestor a@924404dff337
135 premerge successful
135 premerge successful
136 updating: rev 3/3 files (100.00%)
136 updating: rev 3/3 files (100.00%)
137 picked tool 'python ../merge' for rev (binary False symlink False)
137 picked tool 'python ../merge' for rev (binary False symlink False)
138 merging rev
138 merging rev
139 my rev@86a2aa42fc76+ other rev@f4db7e329e71 ancestor rev@924404dff337
139 my rev@86a2aa42fc76+ other rev@f4db7e329e71 ancestor rev@924404dff337
140 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
140 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
141 (branch merge, don't forget to commit)
141 (branch merge, don't forget to commit)
142 --------------
142 --------------
143 M a
143 M a
144 M b
144 M b
145 a
145 a
146 --------------
146 --------------
147
147
148 $ tm "up a " "nm a b" " " "3 get local a change to b, remove a"
148 $ tm "up a " "nm a b" " " "3 get local a change to b, remove a"
149 created new head
149 created new head
150 --------------
150 --------------
151 test L:up a R:nm a b W: - 3 get local a change to b, remove a
151 test L:up a R:nm a b W: - 3 get local a change to b, remove a
152 --------------
152 --------------
153 searching for copies back to rev 1
153 searching for copies back to rev 1
154 unmatched files in other:
154 unmatched files in other:
155 b
155 b
156 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
156 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
157 src: 'a' -> dst: 'b' *
157 src: 'a' -> dst: 'b' *
158 checking for directory renames
158 checking for directory renames
159 resolving manifests
159 resolving manifests
160 overwrite: False, partial: False
160 overwrite: False, partial: False
161 ancestor: 924404dff337, local: e300d1c794ec+, remote: bdb19105162a
161 ancestor: 924404dff337, local: e300d1c794ec+, remote: bdb19105162a
162 a: remote moved to b -> m
163 preserving a for resolve of b
162 rev: versions differ -> m
164 rev: versions differ -> m
163 a: remote moved to b -> m
165 preserving rev for resolve of rev
164 preserving a for resolve of b
165 preserving rev for resolve of rev
166 removing a
166 removing a
167 updating: a 1/2 files (50.00%)
167 updating: a 1/2 files (50.00%)
168 picked tool 'python ../merge' for b (binary False symlink False)
168 picked tool 'python ../merge' for b (binary False symlink False)
169 merging a and b to b
169 merging a and b to b
170 my b@e300d1c794ec+ other b@bdb19105162a ancestor a@924404dff337
170 my b@e300d1c794ec+ other b@bdb19105162a ancestor a@924404dff337
171 premerge successful
171 premerge successful
172 updating: rev 2/2 files (100.00%)
172 updating: rev 2/2 files (100.00%)
173 picked tool 'python ../merge' for rev (binary False symlink False)
173 picked tool 'python ../merge' for rev (binary False symlink False)
174 merging rev
174 merging rev
175 my rev@e300d1c794ec+ other rev@bdb19105162a ancestor rev@924404dff337
175 my rev@e300d1c794ec+ other rev@bdb19105162a ancestor rev@924404dff337
176 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
176 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
177 (branch merge, don't forget to commit)
177 (branch merge, don't forget to commit)
178 --------------
178 --------------
179 M b
179 M b
180 a
180 a
181 --------------
181 --------------
182
182
183 $ tm "nm a b" "up a " " " "4 get remote change to b"
183 $ tm "nm a b" "up a " " " "4 get remote change to b"
184 created new head
184 created new head
185 --------------
185 --------------
186 test L:nm a b R:up a W: - 4 get remote change to b
186 test L:nm a b R:up a W: - 4 get remote change to b
187 --------------
187 --------------
188 searching for copies back to rev 1
188 searching for copies back to rev 1
189 unmatched files in local:
189 unmatched files in local:
190 b
190 b
191 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
191 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
192 src: 'a' -> dst: 'b' *
192 src: 'a' -> dst: 'b' *
193 checking for directory renames
193 checking for directory renames
194 resolving manifests
194 resolving manifests
195 overwrite: False, partial: False
195 overwrite: False, partial: False
196 ancestor: 924404dff337, local: 02963e448370+, remote: f4db7e329e71
196 ancestor: 924404dff337, local: 02963e448370+, remote: f4db7e329e71
197 b: local copied/moved to a -> m
197 b: local copied/moved to a -> m
198 preserving b for resolve of b
198 rev: versions differ -> m
199 rev: versions differ -> m
199 preserving b for resolve of b
200 preserving rev for resolve of rev
200 preserving rev for resolve of rev
201 updating: b 1/2 files (50.00%)
201 updating: b 1/2 files (50.00%)
202 picked tool 'python ../merge' for b (binary False symlink False)
202 picked tool 'python ../merge' for b (binary False symlink False)
203 merging b and a to b
203 merging b and a to b
204 my b@02963e448370+ other a@f4db7e329e71 ancestor a@924404dff337
204 my b@02963e448370+ other a@f4db7e329e71 ancestor a@924404dff337
205 premerge successful
205 premerge successful
206 updating: rev 2/2 files (100.00%)
206 updating: rev 2/2 files (100.00%)
207 picked tool 'python ../merge' for rev (binary False symlink False)
207 picked tool 'python ../merge' for rev (binary False symlink False)
208 merging rev
208 merging rev
209 my rev@02963e448370+ other rev@f4db7e329e71 ancestor rev@924404dff337
209 my rev@02963e448370+ other rev@f4db7e329e71 ancestor rev@924404dff337
210 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
210 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
211 (branch merge, don't forget to commit)
211 (branch merge, don't forget to commit)
212 --------------
212 --------------
213 M b
213 M b
214 a
214 a
215 --------------
215 --------------
216
216
217 $ tm " " "nc a b" " " "5 get b"
217 $ tm " " "nc a b" " " "5 get b"
218 created new head
218 created new head
219 --------------
219 --------------
220 test L: R:nc a b W: - 5 get b
220 test L: R:nc a b W: - 5 get b
221 --------------
221 --------------
222 searching for copies back to rev 1
222 searching for copies back to rev 1
223 unmatched files in other:
223 unmatched files in other:
224 b
224 b
225 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
225 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
226 src: 'a' -> dst: 'b'
226 src: 'a' -> dst: 'b'
227 checking for directory renames
227 checking for directory renames
228 resolving manifests
228 resolving manifests
229 overwrite: False, partial: False
229 overwrite: False, partial: False
230 ancestor: 924404dff337, local: 94b33a1b7f2d+, remote: 4ce40f5aca24
230 ancestor: 924404dff337, local: 94b33a1b7f2d+, remote: 4ce40f5aca24
231 b: remote created -> g
231 rev: versions differ -> m
232 rev: versions differ -> m
232 b: remote created -> g
233 preserving rev for resolve of rev
233 preserving rev for resolve of rev
234 updating: b 1/2 files (50.00%)
234 updating: b 1/2 files (50.00%)
235 getting b
235 getting b
236 updating: rev 2/2 files (100.00%)
236 updating: rev 2/2 files (100.00%)
237 picked tool 'python ../merge' for rev (binary False symlink False)
237 picked tool 'python ../merge' for rev (binary False symlink False)
238 merging rev
238 merging rev
239 my rev@94b33a1b7f2d+ other rev@4ce40f5aca24 ancestor rev@924404dff337
239 my rev@94b33a1b7f2d+ other rev@4ce40f5aca24 ancestor rev@924404dff337
240 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
240 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
241 (branch merge, don't forget to commit)
241 (branch merge, don't forget to commit)
242 --------------
242 --------------
243 M b
243 M b
244 C a
244 C a
245 --------------
245 --------------
246
246
247 $ tm "nc a b" " " " " "6 nothing"
247 $ tm "nc a b" " " " " "6 nothing"
248 created new head
248 created new head
249 --------------
249 --------------
250 test L:nc a b R: W: - 6 nothing
250 test L:nc a b R: W: - 6 nothing
251 --------------
251 --------------
252 searching for copies back to rev 1
252 searching for copies back to rev 1
253 unmatched files in local:
253 unmatched files in local:
254 b
254 b
255 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
255 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
256 src: 'a' -> dst: 'b'
256 src: 'a' -> dst: 'b'
257 checking for directory renames
257 checking for directory renames
258 resolving manifests
258 resolving manifests
259 overwrite: False, partial: False
259 overwrite: False, partial: False
260 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 97c705ade336
260 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 97c705ade336
261 rev: versions differ -> m
261 rev: versions differ -> m
262 preserving rev for resolve of rev
262 preserving rev for resolve of rev
263 updating: rev 1/1 files (100.00%)
263 updating: rev 1/1 files (100.00%)
264 picked tool 'python ../merge' for rev (binary False symlink False)
264 picked tool 'python ../merge' for rev (binary False symlink False)
265 merging rev
265 merging rev
266 my rev@86a2aa42fc76+ other rev@97c705ade336 ancestor rev@924404dff337
266 my rev@86a2aa42fc76+ other rev@97c705ade336 ancestor rev@924404dff337
267 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
267 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
268 (branch merge, don't forget to commit)
268 (branch merge, don't forget to commit)
269 --------------
269 --------------
270 C a
270 C a
271 C b
271 C b
272 --------------
272 --------------
273
273
274 $ tm " " "nm a b" " " "7 get b"
274 $ tm " " "nm a b" " " "7 get b"
275 created new head
275 created new head
276 --------------
276 --------------
277 test L: R:nm a b W: - 7 get b
277 test L: R:nm a b W: - 7 get b
278 --------------
278 --------------
279 searching for copies back to rev 1
279 searching for copies back to rev 1
280 unmatched files in other:
280 unmatched files in other:
281 b
281 b
282 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
282 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
283 src: 'a' -> dst: 'b'
283 src: 'a' -> dst: 'b'
284 checking for directory renames
284 checking for directory renames
285 resolving manifests
285 resolving manifests
286 overwrite: False, partial: False
286 overwrite: False, partial: False
287 ancestor: 924404dff337, local: 94b33a1b7f2d+, remote: bdb19105162a
287 ancestor: 924404dff337, local: 94b33a1b7f2d+, remote: bdb19105162a
288 a: other deleted -> r
288 a: other deleted -> r
289 b: remote created -> g
289 rev: versions differ -> m
290 rev: versions differ -> m
290 b: remote created -> g
291 preserving rev for resolve of rev
291 preserving rev for resolve of rev
292 updating: a 1/3 files (33.33%)
292 updating: a 1/3 files (33.33%)
293 removing a
293 removing a
294 updating: b 2/3 files (66.67%)
294 updating: b 2/3 files (66.67%)
295 getting b
295 getting b
296 updating: rev 3/3 files (100.00%)
296 updating: rev 3/3 files (100.00%)
297 picked tool 'python ../merge' for rev (binary False symlink False)
297 picked tool 'python ../merge' for rev (binary False symlink False)
298 merging rev
298 merging rev
299 my rev@94b33a1b7f2d+ other rev@bdb19105162a ancestor rev@924404dff337
299 my rev@94b33a1b7f2d+ other rev@bdb19105162a ancestor rev@924404dff337
300 1 files updated, 1 files merged, 1 files removed, 0 files unresolved
300 1 files updated, 1 files merged, 1 files removed, 0 files unresolved
301 (branch merge, don't forget to commit)
301 (branch merge, don't forget to commit)
302 --------------
302 --------------
303 M b
303 M b
304 --------------
304 --------------
305
305
306 $ tm "nm a b" " " " " "8 nothing"
306 $ tm "nm a b" " " " " "8 nothing"
307 created new head
307 created new head
308 --------------
308 --------------
309 test L:nm a b R: W: - 8 nothing
309 test L:nm a b R: W: - 8 nothing
310 --------------
310 --------------
311 searching for copies back to rev 1
311 searching for copies back to rev 1
312 unmatched files in local:
312 unmatched files in local:
313 b
313 b
314 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
314 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
315 src: 'a' -> dst: 'b'
315 src: 'a' -> dst: 'b'
316 checking for directory renames
316 checking for directory renames
317 resolving manifests
317 resolving manifests
318 overwrite: False, partial: False
318 overwrite: False, partial: False
319 ancestor: 924404dff337, local: 02963e448370+, remote: 97c705ade336
319 ancestor: 924404dff337, local: 02963e448370+, remote: 97c705ade336
320 rev: versions differ -> m
320 rev: versions differ -> m
321 preserving rev for resolve of rev
321 preserving rev for resolve of rev
322 updating: rev 1/1 files (100.00%)
322 updating: rev 1/1 files (100.00%)
323 picked tool 'python ../merge' for rev (binary False symlink False)
323 picked tool 'python ../merge' for rev (binary False symlink False)
324 merging rev
324 merging rev
325 my rev@02963e448370+ other rev@97c705ade336 ancestor rev@924404dff337
325 my rev@02963e448370+ other rev@97c705ade336 ancestor rev@924404dff337
326 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
326 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
327 (branch merge, don't forget to commit)
327 (branch merge, don't forget to commit)
328 --------------
328 --------------
329 C b
329 C b
330 --------------
330 --------------
331
331
332 $ tm "um a b" "um a b" " " "9 do merge with ancestor in a"
332 $ tm "um a b" "um a b" " " "9 do merge with ancestor in a"
333 created new head
333 created new head
334 --------------
334 --------------
335 test L:um a b R:um a b W: - 9 do merge with ancestor in a
335 test L:um a b R:um a b W: - 9 do merge with ancestor in a
336 --------------
336 --------------
337 searching for copies back to rev 1
337 searching for copies back to rev 1
338 resolving manifests
338 resolving manifests
339 overwrite: False, partial: False
339 overwrite: False, partial: False
340 ancestor: 924404dff337, local: 62e7bf090eba+, remote: 49b6d8032493
340 ancestor: 924404dff337, local: 62e7bf090eba+, remote: 49b6d8032493
341 b: versions differ -> m
341 b: versions differ -> m
342 preserving b for resolve of b
342 rev: versions differ -> m
343 rev: versions differ -> m
343 preserving b for resolve of b
344 preserving rev for resolve of rev
344 preserving rev for resolve of rev
345 updating: b 1/2 files (50.00%)
345 updating: b 1/2 files (50.00%)
346 picked tool 'python ../merge' for b (binary False symlink False)
346 picked tool 'python ../merge' for b (binary False symlink False)
347 merging b
347 merging b
348 my b@62e7bf090eba+ other b@49b6d8032493 ancestor a@924404dff337
348 my b@62e7bf090eba+ other b@49b6d8032493 ancestor a@924404dff337
349 updating: rev 2/2 files (100.00%)
349 updating: rev 2/2 files (100.00%)
350 picked tool 'python ../merge' for rev (binary False symlink False)
350 picked tool 'python ../merge' for rev (binary False symlink False)
351 merging rev
351 merging rev
352 my rev@62e7bf090eba+ other rev@49b6d8032493 ancestor rev@924404dff337
352 my rev@62e7bf090eba+ other rev@49b6d8032493 ancestor rev@924404dff337
353 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
353 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
354 (branch merge, don't forget to commit)
354 (branch merge, don't forget to commit)
355 --------------
355 --------------
356 M b
356 M b
357 --------------
357 --------------
358
358
359
359
360 m "um a c" "um x c" " " "10 do merge with no ancestor"
360 m "um a c" "um x c" " " "10 do merge with no ancestor"
361
361
362 $ tm "nm a b" "nm a c" " " "11 get c, keep b"
362 $ tm "nm a b" "nm a c" " " "11 get c, keep b"
363 created new head
363 created new head
364 --------------
364 --------------
365 test L:nm a b R:nm a c W: - 11 get c, keep b
365 test L:nm a b R:nm a c W: - 11 get c, keep b
366 --------------
366 --------------
367 searching for copies back to rev 1
367 searching for copies back to rev 1
368 unmatched files in local:
368 unmatched files in local:
369 b
369 b
370 unmatched files in other:
370 unmatched files in other:
371 c
371 c
372 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
372 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
373 src: 'a' -> dst: 'b' !
373 src: 'a' -> dst: 'b' !
374 src: 'a' -> dst: 'c' !
374 src: 'a' -> dst: 'c' !
375 checking for directory renames
375 checking for directory renames
376 a: divergent renames -> dr
377 resolving manifests
376 resolving manifests
378 overwrite: False, partial: False
377 overwrite: False, partial: False
379 ancestor: 924404dff337, local: 02963e448370+, remote: fe905ef2c33e
378 ancestor: 924404dff337, local: 02963e448370+, remote: fe905ef2c33e
380 rev: versions differ -> m
379 a: divergent renames -> dr
381 c: remote created -> g
380 c: remote created -> g
382 preserving rev for resolve of rev
381 rev: versions differ -> m
382 preserving rev for resolve of rev
383 updating: a 1/3 files (33.33%)
383 updating: a 1/3 files (33.33%)
384 note: possible conflict - a was renamed multiple times to:
384 note: possible conflict - a was renamed multiple times to:
385 b
385 b
386 c
386 c
387 updating: c 2/3 files (66.67%)
387 updating: c 2/3 files (66.67%)
388 getting c
388 getting c
389 updating: rev 3/3 files (100.00%)
389 updating: rev 3/3 files (100.00%)
390 picked tool 'python ../merge' for rev (binary False symlink False)
390 picked tool 'python ../merge' for rev (binary False symlink False)
391 merging rev
391 merging rev
392 my rev@02963e448370+ other rev@fe905ef2c33e ancestor rev@924404dff337
392 my rev@02963e448370+ other rev@fe905ef2c33e ancestor rev@924404dff337
393 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
393 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
394 (branch merge, don't forget to commit)
394 (branch merge, don't forget to commit)
395 --------------
395 --------------
396 M c
396 M c
397 C b
397 C b
398 --------------
398 --------------
399
399
400 $ tm "nc a b" "up b " " " "12 merge b no ancestor"
400 $ tm "nc a b" "up b " " " "12 merge b no ancestor"
401 created new head
401 created new head
402 --------------
402 --------------
403 test L:nc a b R:up b W: - 12 merge b no ancestor
403 test L:nc a b R:up b W: - 12 merge b no ancestor
404 --------------
404 --------------
405 searching for copies back to rev 1
405 searching for copies back to rev 1
406 resolving manifests
406 resolving manifests
407 overwrite: False, partial: False
407 overwrite: False, partial: False
408 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: af30c7647fc7
408 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: af30c7647fc7
409 b: versions differ -> m
409 b: versions differ -> m
410 preserving b for resolve of b
410 rev: versions differ -> m
411 rev: versions differ -> m
411 preserving b for resolve of b
412 preserving rev for resolve of rev
412 preserving rev for resolve of rev
413 updating: b 1/2 files (50.00%)
413 updating: b 1/2 files (50.00%)
414 picked tool 'python ../merge' for b (binary False symlink False)
414 picked tool 'python ../merge' for b (binary False symlink False)
415 merging b
415 merging b
416 my b@86a2aa42fc76+ other b@af30c7647fc7 ancestor b@000000000000
416 my b@86a2aa42fc76+ other b@af30c7647fc7 ancestor b@000000000000
417 updating: rev 2/2 files (100.00%)
417 updating: rev 2/2 files (100.00%)
418 picked tool 'python ../merge' for rev (binary False symlink False)
418 picked tool 'python ../merge' for rev (binary False symlink False)
419 merging rev
419 merging rev
420 my rev@86a2aa42fc76+ other rev@af30c7647fc7 ancestor rev@924404dff337
420 my rev@86a2aa42fc76+ other rev@af30c7647fc7 ancestor rev@924404dff337
421 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
421 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
422 (branch merge, don't forget to commit)
422 (branch merge, don't forget to commit)
423 --------------
423 --------------
424 M b
424 M b
425 C a
425 C a
426 --------------
426 --------------
427
427
428 $ tm "up b " "nm a b" " " "13 merge b no ancestor"
428 $ tm "up b " "nm a b" " " "13 merge b no ancestor"
429 created new head
429 created new head
430 --------------
430 --------------
431 test L:up b R:nm a b W: - 13 merge b no ancestor
431 test L:up b R:nm a b W: - 13 merge b no ancestor
432 --------------
432 --------------
433 searching for copies back to rev 1
433 searching for copies back to rev 1
434 resolving manifests
434 resolving manifests
435 overwrite: False, partial: False
435 overwrite: False, partial: False
436 ancestor: 924404dff337, local: 59318016310c+, remote: bdb19105162a
436 ancestor: 924404dff337, local: 59318016310c+, remote: bdb19105162a
437 a: other deleted -> r
437 a: other deleted -> r
438 b: versions differ -> m
438 b: versions differ -> m
439 preserving b for resolve of b
439 rev: versions differ -> m
440 rev: versions differ -> m
440 preserving b for resolve of b
441 preserving rev for resolve of rev
441 preserving rev for resolve of rev
442 updating: a 1/3 files (33.33%)
442 updating: a 1/3 files (33.33%)
443 removing a
443 removing a
444 updating: b 2/3 files (66.67%)
444 updating: b 2/3 files (66.67%)
445 picked tool 'python ../merge' for b (binary False symlink False)
445 picked tool 'python ../merge' for b (binary False symlink False)
446 merging b
446 merging b
447 my b@59318016310c+ other b@bdb19105162a ancestor b@000000000000
447 my b@59318016310c+ other b@bdb19105162a ancestor b@000000000000
448 updating: rev 3/3 files (100.00%)
448 updating: rev 3/3 files (100.00%)
449 picked tool 'python ../merge' for rev (binary False symlink False)
449 picked tool 'python ../merge' for rev (binary False symlink False)
450 merging rev
450 merging rev
451 my rev@59318016310c+ other rev@bdb19105162a ancestor rev@924404dff337
451 my rev@59318016310c+ other rev@bdb19105162a ancestor rev@924404dff337
452 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
452 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
453 (branch merge, don't forget to commit)
453 (branch merge, don't forget to commit)
454 --------------
454 --------------
455 M b
455 M b
456 --------------
456 --------------
457
457
458 $ tm "nc a b" "up a b" " " "14 merge b no ancestor"
458 $ tm "nc a b" "up a b" " " "14 merge b no ancestor"
459 created new head
459 created new head
460 --------------
460 --------------
461 test L:nc a b R:up a b W: - 14 merge b no ancestor
461 test L:nc a b R:up a b W: - 14 merge b no ancestor
462 --------------
462 --------------
463 searching for copies back to rev 1
463 searching for copies back to rev 1
464 resolving manifests
464 resolving manifests
465 overwrite: False, partial: False
465 overwrite: False, partial: False
466 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 8dbce441892a
466 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 8dbce441892a
467 a: remote is newer -> g
467 a: remote is newer -> g
468 b: versions differ -> m
468 b: versions differ -> m
469 preserving b for resolve of b
469 rev: versions differ -> m
470 rev: versions differ -> m
470 preserving b for resolve of b
471 preserving rev for resolve of rev
471 preserving rev for resolve of rev
472 updating: a 1/3 files (33.33%)
472 updating: a 1/3 files (33.33%)
473 getting a
473 getting a
474 updating: b 2/3 files (66.67%)
474 updating: b 2/3 files (66.67%)
475 picked tool 'python ../merge' for b (binary False symlink False)
475 picked tool 'python ../merge' for b (binary False symlink False)
476 merging b
476 merging b
477 my b@86a2aa42fc76+ other b@8dbce441892a ancestor b@000000000000
477 my b@86a2aa42fc76+ other b@8dbce441892a ancestor b@000000000000
478 updating: rev 3/3 files (100.00%)
478 updating: rev 3/3 files (100.00%)
479 picked tool 'python ../merge' for rev (binary False symlink False)
479 picked tool 'python ../merge' for rev (binary False symlink False)
480 merging rev
480 merging rev
481 my rev@86a2aa42fc76+ other rev@8dbce441892a ancestor rev@924404dff337
481 my rev@86a2aa42fc76+ other rev@8dbce441892a ancestor rev@924404dff337
482 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
482 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
483 (branch merge, don't forget to commit)
483 (branch merge, don't forget to commit)
484 --------------
484 --------------
485 M a
485 M a
486 M b
486 M b
487 --------------
487 --------------
488
488
489 $ tm "up b " "nm a b" " " "15 merge b no ancestor, remove a"
489 $ tm "up b " "nm a b" " " "15 merge b no ancestor, remove a"
490 created new head
490 created new head
491 --------------
491 --------------
492 test L:up b R:nm a b W: - 15 merge b no ancestor, remove a
492 test L:up b R:nm a b W: - 15 merge b no ancestor, remove a
493 --------------
493 --------------
494 searching for copies back to rev 1
494 searching for copies back to rev 1
495 resolving manifests
495 resolving manifests
496 overwrite: False, partial: False
496 overwrite: False, partial: False
497 ancestor: 924404dff337, local: 59318016310c+, remote: bdb19105162a
497 ancestor: 924404dff337, local: 59318016310c+, remote: bdb19105162a
498 a: other deleted -> r
498 a: other deleted -> r
499 b: versions differ -> m
499 b: versions differ -> m
500 preserving b for resolve of b
500 rev: versions differ -> m
501 rev: versions differ -> m
501 preserving b for resolve of b
502 preserving rev for resolve of rev
502 preserving rev for resolve of rev
503 updating: a 1/3 files (33.33%)
503 updating: a 1/3 files (33.33%)
504 removing a
504 removing a
505 updating: b 2/3 files (66.67%)
505 updating: b 2/3 files (66.67%)
506 picked tool 'python ../merge' for b (binary False symlink False)
506 picked tool 'python ../merge' for b (binary False symlink False)
507 merging b
507 merging b
508 my b@59318016310c+ other b@bdb19105162a ancestor b@000000000000
508 my b@59318016310c+ other b@bdb19105162a ancestor b@000000000000
509 updating: rev 3/3 files (100.00%)
509 updating: rev 3/3 files (100.00%)
510 picked tool 'python ../merge' for rev (binary False symlink False)
510 picked tool 'python ../merge' for rev (binary False symlink False)
511 merging rev
511 merging rev
512 my rev@59318016310c+ other rev@bdb19105162a ancestor rev@924404dff337
512 my rev@59318016310c+ other rev@bdb19105162a ancestor rev@924404dff337
513 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
513 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
514 (branch merge, don't forget to commit)
514 (branch merge, don't forget to commit)
515 --------------
515 --------------
516 M b
516 M b
517 --------------
517 --------------
518
518
519 $ tm "nc a b" "up a b" " " "16 get a, merge b no ancestor"
519 $ tm "nc a b" "up a b" " " "16 get a, merge b no ancestor"
520 created new head
520 created new head
521 --------------
521 --------------
522 test L:nc a b R:up a b W: - 16 get a, merge b no ancestor
522 test L:nc a b R:up a b W: - 16 get a, merge b no ancestor
523 --------------
523 --------------
524 searching for copies back to rev 1
524 searching for copies back to rev 1
525 resolving manifests
525 resolving manifests
526 overwrite: False, partial: False
526 overwrite: False, partial: False
527 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 8dbce441892a
527 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 8dbce441892a
528 a: remote is newer -> g
528 a: remote is newer -> g
529 b: versions differ -> m
529 b: versions differ -> m
530 preserving b for resolve of b
530 rev: versions differ -> m
531 rev: versions differ -> m
531 preserving b for resolve of b
532 preserving rev for resolve of rev
532 preserving rev for resolve of rev
533 updating: a 1/3 files (33.33%)
533 updating: a 1/3 files (33.33%)
534 getting a
534 getting a
535 updating: b 2/3 files (66.67%)
535 updating: b 2/3 files (66.67%)
536 picked tool 'python ../merge' for b (binary False symlink False)
536 picked tool 'python ../merge' for b (binary False symlink False)
537 merging b
537 merging b
538 my b@86a2aa42fc76+ other b@8dbce441892a ancestor b@000000000000
538 my b@86a2aa42fc76+ other b@8dbce441892a ancestor b@000000000000
539 updating: rev 3/3 files (100.00%)
539 updating: rev 3/3 files (100.00%)
540 picked tool 'python ../merge' for rev (binary False symlink False)
540 picked tool 'python ../merge' for rev (binary False symlink False)
541 merging rev
541 merging rev
542 my rev@86a2aa42fc76+ other rev@8dbce441892a ancestor rev@924404dff337
542 my rev@86a2aa42fc76+ other rev@8dbce441892a ancestor rev@924404dff337
543 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
543 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
544 (branch merge, don't forget to commit)
544 (branch merge, don't forget to commit)
545 --------------
545 --------------
546 M a
546 M a
547 M b
547 M b
548 --------------
548 --------------
549
549
550 $ tm "up a b" "nc a b" " " "17 keep a, merge b no ancestor"
550 $ tm "up a b" "nc a b" " " "17 keep a, merge b no ancestor"
551 created new head
551 created new head
552 --------------
552 --------------
553 test L:up a b R:nc a b W: - 17 keep a, merge b no ancestor
553 test L:up a b R:nc a b W: - 17 keep a, merge b no ancestor
554 --------------
554 --------------
555 searching for copies back to rev 1
555 searching for copies back to rev 1
556 resolving manifests
556 resolving manifests
557 overwrite: False, partial: False
557 overwrite: False, partial: False
558 ancestor: 924404dff337, local: 0b76e65c8289+, remote: 4ce40f5aca24
558 ancestor: 924404dff337, local: 0b76e65c8289+, remote: 4ce40f5aca24
559 b: versions differ -> m
559 b: versions differ -> m
560 preserving b for resolve of b
560 rev: versions differ -> m
561 rev: versions differ -> m
561 preserving b for resolve of b
562 preserving rev for resolve of rev
562 preserving rev for resolve of rev
563 updating: b 1/2 files (50.00%)
563 updating: b 1/2 files (50.00%)
564 picked tool 'python ../merge' for b (binary False symlink False)
564 picked tool 'python ../merge' for b (binary False symlink False)
565 merging b
565 merging b
566 my b@0b76e65c8289+ other b@4ce40f5aca24 ancestor b@000000000000
566 my b@0b76e65c8289+ other b@4ce40f5aca24 ancestor b@000000000000
567 updating: rev 2/2 files (100.00%)
567 updating: rev 2/2 files (100.00%)
568 picked tool 'python ../merge' for rev (binary False symlink False)
568 picked tool 'python ../merge' for rev (binary False symlink False)
569 merging rev
569 merging rev
570 my rev@0b76e65c8289+ other rev@4ce40f5aca24 ancestor rev@924404dff337
570 my rev@0b76e65c8289+ other rev@4ce40f5aca24 ancestor rev@924404dff337
571 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
571 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
572 (branch merge, don't forget to commit)
572 (branch merge, don't forget to commit)
573 --------------
573 --------------
574 M b
574 M b
575 C a
575 C a
576 --------------
576 --------------
577
577
578 $ tm "nm a b" "up a b" " " "18 merge b no ancestor"
578 $ tm "nm a b" "up a b" " " "18 merge b no ancestor"
579 created new head
579 created new head
580 --------------
580 --------------
581 test L:nm a b R:up a b W: - 18 merge b no ancestor
581 test L:nm a b R:up a b W: - 18 merge b no ancestor
582 --------------
582 --------------
583 searching for copies back to rev 1
583 searching for copies back to rev 1
584 resolving manifests
584 resolving manifests
585 overwrite: False, partial: False
585 overwrite: False, partial: False
586 ancestor: 924404dff337, local: 02963e448370+, remote: 8dbce441892a
586 ancestor: 924404dff337, local: 02963e448370+, remote: 8dbce441892a
587 b: versions differ -> m
588 rev: versions differ -> m
589 remote changed a which local deleted
587 remote changed a which local deleted
590 use (c)hanged version or leave (d)eleted? c
588 use (c)hanged version or leave (d)eleted? c
591 a: prompt recreating -> g
589 a: prompt recreating -> g
592 preserving b for resolve of b
590 b: versions differ -> m
593 preserving rev for resolve of rev
591 preserving b for resolve of b
592 rev: versions differ -> m
593 preserving rev for resolve of rev
594 updating: a 1/3 files (33.33%)
594 updating: a 1/3 files (33.33%)
595 getting a
595 getting a
596 updating: b 2/3 files (66.67%)
596 updating: b 2/3 files (66.67%)
597 picked tool 'python ../merge' for b (binary False symlink False)
597 picked tool 'python ../merge' for b (binary False symlink False)
598 merging b
598 merging b
599 my b@02963e448370+ other b@8dbce441892a ancestor b@000000000000
599 my b@02963e448370+ other b@8dbce441892a ancestor b@000000000000
600 updating: rev 3/3 files (100.00%)
600 updating: rev 3/3 files (100.00%)
601 picked tool 'python ../merge' for rev (binary False symlink False)
601 picked tool 'python ../merge' for rev (binary False symlink False)
602 merging rev
602 merging rev
603 my rev@02963e448370+ other rev@8dbce441892a ancestor rev@924404dff337
603 my rev@02963e448370+ other rev@8dbce441892a ancestor rev@924404dff337
604 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
604 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
605 (branch merge, don't forget to commit)
605 (branch merge, don't forget to commit)
606 --------------
606 --------------
607 M a
607 M a
608 M b
608 M b
609 --------------
609 --------------
610
610
611 $ tm "up a b" "nm a b" " " "19 merge b no ancestor, prompt remove a"
611 $ tm "up a b" "nm a b" " " "19 merge b no ancestor, prompt remove a"
612 created new head
612 created new head
613 --------------
613 --------------
614 test L:up a b R:nm a b W: - 19 merge b no ancestor, prompt remove a
614 test L:up a b R:nm a b W: - 19 merge b no ancestor, prompt remove a
615 --------------
615 --------------
616 searching for copies back to rev 1
616 searching for copies back to rev 1
617 resolving manifests
617 resolving manifests
618 overwrite: False, partial: False
618 overwrite: False, partial: False
619 ancestor: 924404dff337, local: 0b76e65c8289+, remote: bdb19105162a
619 ancestor: 924404dff337, local: 0b76e65c8289+, remote: bdb19105162a
620 b: versions differ -> m
621 rev: versions differ -> m
622 local changed a which remote deleted
620 local changed a which remote deleted
623 use (c)hanged version or (d)elete? c
621 use (c)hanged version or (d)elete? c
624 a: prompt keep -> a
622 a: prompt keep -> a
625 preserving b for resolve of b
623 b: versions differ -> m
626 preserving rev for resolve of rev
624 preserving b for resolve of b
625 rev: versions differ -> m
626 preserving rev for resolve of rev
627 updating: a 1/3 files (33.33%)
627 updating: a 1/3 files (33.33%)
628 updating: b 2/3 files (66.67%)
628 updating: b 2/3 files (66.67%)
629 picked tool 'python ../merge' for b (binary False symlink False)
629 picked tool 'python ../merge' for b (binary False symlink False)
630 merging b
630 merging b
631 my b@0b76e65c8289+ other b@bdb19105162a ancestor b@000000000000
631 my b@0b76e65c8289+ other b@bdb19105162a ancestor b@000000000000
632 updating: rev 3/3 files (100.00%)
632 updating: rev 3/3 files (100.00%)
633 picked tool 'python ../merge' for rev (binary False symlink False)
633 picked tool 'python ../merge' for rev (binary False symlink False)
634 merging rev
634 merging rev
635 my rev@0b76e65c8289+ other rev@bdb19105162a ancestor rev@924404dff337
635 my rev@0b76e65c8289+ other rev@bdb19105162a ancestor rev@924404dff337
636 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
636 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
637 (branch merge, don't forget to commit)
637 (branch merge, don't forget to commit)
638 --------------
638 --------------
639 M b
639 M b
640 C a
640 C a
641 --------------
641 --------------
642
642
643 $ tm "up a " "um a b" " " "20 merge a and b to b, remove a"
643 $ tm "up a " "um a b" " " "20 merge a and b to b, remove a"
644 created new head
644 created new head
645 --------------
645 --------------
646 test L:up a R:um a b W: - 20 merge a and b to b, remove a
646 test L:up a R:um a b W: - 20 merge a and b to b, remove a
647 --------------
647 --------------
648 searching for copies back to rev 1
648 searching for copies back to rev 1
649 unmatched files in other:
649 unmatched files in other:
650 b
650 b
651 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
651 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
652 src: 'a' -> dst: 'b' *
652 src: 'a' -> dst: 'b' *
653 checking for directory renames
653 checking for directory renames
654 resolving manifests
654 resolving manifests
655 overwrite: False, partial: False
655 overwrite: False, partial: False
656 ancestor: 924404dff337, local: e300d1c794ec+, remote: 49b6d8032493
656 ancestor: 924404dff337, local: e300d1c794ec+, remote: 49b6d8032493
657 a: remote moved to b -> m
658 preserving a for resolve of b
657 rev: versions differ -> m
659 rev: versions differ -> m
658 a: remote moved to b -> m
660 preserving rev for resolve of rev
659 preserving a for resolve of b
660 preserving rev for resolve of rev
661 removing a
661 removing a
662 updating: a 1/2 files (50.00%)
662 updating: a 1/2 files (50.00%)
663 picked tool 'python ../merge' for b (binary False symlink False)
663 picked tool 'python ../merge' for b (binary False symlink False)
664 merging a and b to b
664 merging a and b to b
665 my b@e300d1c794ec+ other b@49b6d8032493 ancestor a@924404dff337
665 my b@e300d1c794ec+ other b@49b6d8032493 ancestor a@924404dff337
666 updating: rev 2/2 files (100.00%)
666 updating: rev 2/2 files (100.00%)
667 picked tool 'python ../merge' for rev (binary False symlink False)
667 picked tool 'python ../merge' for rev (binary False symlink False)
668 merging rev
668 merging rev
669 my rev@e300d1c794ec+ other rev@49b6d8032493 ancestor rev@924404dff337
669 my rev@e300d1c794ec+ other rev@49b6d8032493 ancestor rev@924404dff337
670 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
670 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
671 (branch merge, don't forget to commit)
671 (branch merge, don't forget to commit)
672 --------------
672 --------------
673 M b
673 M b
674 a
674 a
675 --------------
675 --------------
676
676
677 $ tm "um a b" "up a " " " "21 merge a and b to b"
677 $ tm "um a b" "up a " " " "21 merge a and b to b"
678 created new head
678 created new head
679 --------------
679 --------------
680 test L:um a b R:up a W: - 21 merge a and b to b
680 test L:um a b R:up a W: - 21 merge a and b to b
681 --------------
681 --------------
682 searching for copies back to rev 1
682 searching for copies back to rev 1
683 unmatched files in local:
683 unmatched files in local:
684 b
684 b
685 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
685 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
686 src: 'a' -> dst: 'b' *
686 src: 'a' -> dst: 'b' *
687 checking for directory renames
687 checking for directory renames
688 resolving manifests
688 resolving manifests
689 overwrite: False, partial: False
689 overwrite: False, partial: False
690 ancestor: 924404dff337, local: 62e7bf090eba+, remote: f4db7e329e71
690 ancestor: 924404dff337, local: 62e7bf090eba+, remote: f4db7e329e71
691 b: local copied/moved to a -> m
691 b: local copied/moved to a -> m
692 preserving b for resolve of b
692 rev: versions differ -> m
693 rev: versions differ -> m
693 preserving b for resolve of b
694 preserving rev for resolve of rev
694 preserving rev for resolve of rev
695 updating: b 1/2 files (50.00%)
695 updating: b 1/2 files (50.00%)
696 picked tool 'python ../merge' for b (binary False symlink False)
696 picked tool 'python ../merge' for b (binary False symlink False)
697 merging b and a to b
697 merging b and a to b
698 my b@62e7bf090eba+ other a@f4db7e329e71 ancestor a@924404dff337
698 my b@62e7bf090eba+ other a@f4db7e329e71 ancestor a@924404dff337
699 updating: rev 2/2 files (100.00%)
699 updating: rev 2/2 files (100.00%)
700 picked tool 'python ../merge' for rev (binary False symlink False)
700 picked tool 'python ../merge' for rev (binary False symlink False)
701 merging rev
701 merging rev
702 my rev@62e7bf090eba+ other rev@f4db7e329e71 ancestor rev@924404dff337
702 my rev@62e7bf090eba+ other rev@f4db7e329e71 ancestor rev@924404dff337
703 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
703 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
704 (branch merge, don't forget to commit)
704 (branch merge, don't forget to commit)
705 --------------
705 --------------
706 M b
706 M b
707 a
707 a
708 --------------
708 --------------
709
709
710
710
711 m "nm a b" "um x a" " " "22 get a, keep b"
711 m "nm a b" "um x a" " " "22 get a, keep b"
712
712
713 $ tm "nm a b" "up a c" " " "23 get c, keep b"
713 $ tm "nm a b" "up a c" " " "23 get c, keep b"
714 created new head
714 created new head
715 --------------
715 --------------
716 test L:nm a b R:up a c W: - 23 get c, keep b
716 test L:nm a b R:up a c W: - 23 get c, keep b
717 --------------
717 --------------
718 searching for copies back to rev 1
718 searching for copies back to rev 1
719 unmatched files in local:
719 unmatched files in local:
720 b
720 b
721 unmatched files in other:
721 unmatched files in other:
722 c
722 c
723 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
723 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
724 src: 'a' -> dst: 'b' *
724 src: 'a' -> dst: 'b' *
725 checking for directory renames
725 checking for directory renames
726 resolving manifests
726 resolving manifests
727 overwrite: False, partial: False
727 overwrite: False, partial: False
728 ancestor: 924404dff337, local: 02963e448370+, remote: 2b958612230f
728 ancestor: 924404dff337, local: 02963e448370+, remote: 2b958612230f
729 b: local copied/moved to a -> m
729 b: local copied/moved to a -> m
730 rev: versions differ -> m
730 preserving b for resolve of b
731 c: remote created -> g
731 c: remote created -> g
732 preserving b for resolve of b
732 rev: versions differ -> m
733 preserving rev for resolve of rev
733 preserving rev for resolve of rev
734 updating: b 1/3 files (33.33%)
734 updating: b 1/3 files (33.33%)
735 picked tool 'python ../merge' for b (binary False symlink False)
735 picked tool 'python ../merge' for b (binary False symlink False)
736 merging b and a to b
736 merging b and a to b
737 my b@02963e448370+ other a@2b958612230f ancestor a@924404dff337
737 my b@02963e448370+ other a@2b958612230f ancestor a@924404dff337
738 premerge successful
738 premerge successful
739 updating: c 2/3 files (66.67%)
739 updating: c 2/3 files (66.67%)
740 getting c
740 getting c
741 updating: rev 3/3 files (100.00%)
741 updating: rev 3/3 files (100.00%)
742 picked tool 'python ../merge' for rev (binary False symlink False)
742 picked tool 'python ../merge' for rev (binary False symlink False)
743 merging rev
743 merging rev
744 my rev@02963e448370+ other rev@2b958612230f ancestor rev@924404dff337
744 my rev@02963e448370+ other rev@2b958612230f ancestor rev@924404dff337
745 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
745 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
746 (branch merge, don't forget to commit)
746 (branch merge, don't forget to commit)
747 --------------
747 --------------
748 M b
748 M b
749 a
749 a
750 M c
750 M c
751 --------------
751 --------------
752
752
753
753
754 $ cd ..
754 $ cd ..
@@ -1,1088 +1,1088 b''
1 Let commit recurse into subrepos by default to match pre-2.0 behavior:
1 Let commit recurse into subrepos by default to match pre-2.0 behavior:
2
2
3 $ echo "[ui]" >> $HGRCPATH
3 $ echo "[ui]" >> $HGRCPATH
4 $ echo "commitsubrepos = Yes" >> $HGRCPATH
4 $ echo "commitsubrepos = Yes" >> $HGRCPATH
5
5
6 $ hg init t
6 $ hg init t
7 $ cd t
7 $ cd t
8
8
9 first revision, no sub
9 first revision, no sub
10
10
11 $ echo a > a
11 $ echo a > a
12 $ hg ci -Am0
12 $ hg ci -Am0
13 adding a
13 adding a
14
14
15 add first sub
15 add first sub
16
16
17 $ echo s = s > .hgsub
17 $ echo s = s > .hgsub
18 $ hg add .hgsub
18 $ hg add .hgsub
19 $ hg init s
19 $ hg init s
20 $ echo a > s/a
20 $ echo a > s/a
21
21
22 Issue2232: committing a subrepo without .hgsub
22 Issue2232: committing a subrepo without .hgsub
23
23
24 $ hg ci -mbad s
24 $ hg ci -mbad s
25 abort: can't commit subrepos without .hgsub
25 abort: can't commit subrepos without .hgsub
26 [255]
26 [255]
27
27
28 $ hg -R s ci -Ams0
28 $ hg -R s ci -Ams0
29 adding a
29 adding a
30 $ hg sum
30 $ hg sum
31 parent: 0:f7b1eb17ad24 tip
31 parent: 0:f7b1eb17ad24 tip
32 0
32 0
33 branch: default
33 branch: default
34 commit: 1 added, 1 subrepos
34 commit: 1 added, 1 subrepos
35 update: (current)
35 update: (current)
36 $ hg ci -m1
36 $ hg ci -m1
37
37
38 Revert subrepo and test subrepo fileset keyword:
38 Revert subrepo and test subrepo fileset keyword:
39
39
40 $ echo b > s/a
40 $ echo b > s/a
41 $ hg revert "set:subrepo('glob:s*')"
41 $ hg revert "set:subrepo('glob:s*')"
42 reverting subrepo s
42 reverting subrepo s
43 reverting s/a (glob)
43 reverting s/a (glob)
44 $ rm s/a.orig
44 $ rm s/a.orig
45
45
46 Revert subrepo with no backup. The "reverting s/a" line is gone since
46 Revert subrepo with no backup. The "reverting s/a" line is gone since
47 we're really running 'hg update' in the subrepo:
47 we're really running 'hg update' in the subrepo:
48
48
49 $ echo b > s/a
49 $ echo b > s/a
50 $ hg revert --no-backup s
50 $ hg revert --no-backup s
51 reverting subrepo s
51 reverting subrepo s
52
52
53 Issue2022: update -C
53 Issue2022: update -C
54
54
55 $ echo b > s/a
55 $ echo b > s/a
56 $ hg sum
56 $ hg sum
57 parent: 1:7cf8cfea66e4 tip
57 parent: 1:7cf8cfea66e4 tip
58 1
58 1
59 branch: default
59 branch: default
60 commit: 1 subrepos
60 commit: 1 subrepos
61 update: (current)
61 update: (current)
62 $ hg co -C 1
62 $ hg co -C 1
63 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
63 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
64 $ hg sum
64 $ hg sum
65 parent: 1:7cf8cfea66e4 tip
65 parent: 1:7cf8cfea66e4 tip
66 1
66 1
67 branch: default
67 branch: default
68 commit: (clean)
68 commit: (clean)
69 update: (current)
69 update: (current)
70
70
71 commands that require a clean repo should respect subrepos
71 commands that require a clean repo should respect subrepos
72
72
73 $ echo b >> s/a
73 $ echo b >> s/a
74 $ hg backout tip
74 $ hg backout tip
75 abort: uncommitted changes in subrepo s
75 abort: uncommitted changes in subrepo s
76 [255]
76 [255]
77 $ hg revert -C -R s s/a
77 $ hg revert -C -R s s/a
78
78
79 add sub sub
79 add sub sub
80
80
81 $ echo ss = ss > s/.hgsub
81 $ echo ss = ss > s/.hgsub
82 $ hg init s/ss
82 $ hg init s/ss
83 $ echo a > s/ss/a
83 $ echo a > s/ss/a
84 $ hg -R s add s/.hgsub
84 $ hg -R s add s/.hgsub
85 $ hg -R s/ss add s/ss/a
85 $ hg -R s/ss add s/ss/a
86 $ hg sum
86 $ hg sum
87 parent: 1:7cf8cfea66e4 tip
87 parent: 1:7cf8cfea66e4 tip
88 1
88 1
89 branch: default
89 branch: default
90 commit: 1 subrepos
90 commit: 1 subrepos
91 update: (current)
91 update: (current)
92 $ hg ci -m2
92 $ hg ci -m2
93 committing subrepository s
93 committing subrepository s
94 committing subrepository s/ss (glob)
94 committing subrepository s/ss (glob)
95 $ hg sum
95 $ hg sum
96 parent: 2:df30734270ae tip
96 parent: 2:df30734270ae tip
97 2
97 2
98 branch: default
98 branch: default
99 commit: (clean)
99 commit: (clean)
100 update: (current)
100 update: (current)
101
101
102 bump sub rev (and check it is ignored by ui.commitsubrepos)
102 bump sub rev (and check it is ignored by ui.commitsubrepos)
103
103
104 $ echo b > s/a
104 $ echo b > s/a
105 $ hg -R s ci -ms1
105 $ hg -R s ci -ms1
106 $ hg --config ui.commitsubrepos=no ci -m3
106 $ hg --config ui.commitsubrepos=no ci -m3
107
107
108 leave sub dirty (and check ui.commitsubrepos=no aborts the commit)
108 leave sub dirty (and check ui.commitsubrepos=no aborts the commit)
109
109
110 $ echo c > s/a
110 $ echo c > s/a
111 $ hg --config ui.commitsubrepos=no ci -m4
111 $ hg --config ui.commitsubrepos=no ci -m4
112 abort: uncommitted changes in subrepo s
112 abort: uncommitted changes in subrepo s
113 (use --subrepos for recursive commit)
113 (use --subrepos for recursive commit)
114 [255]
114 [255]
115 $ hg id
115 $ hg id
116 f6affe3fbfaa+ tip
116 f6affe3fbfaa+ tip
117 $ hg -R s ci -mc
117 $ hg -R s ci -mc
118 $ hg id
118 $ hg id
119 f6affe3fbfaa+ tip
119 f6affe3fbfaa+ tip
120 $ echo d > s/a
120 $ echo d > s/a
121 $ hg ci -m4
121 $ hg ci -m4
122 committing subrepository s
122 committing subrepository s
123 $ hg tip -R s
123 $ hg tip -R s
124 changeset: 4:02dcf1d70411
124 changeset: 4:02dcf1d70411
125 tag: tip
125 tag: tip
126 user: test
126 user: test
127 date: Thu Jan 01 00:00:00 1970 +0000
127 date: Thu Jan 01 00:00:00 1970 +0000
128 summary: 4
128 summary: 4
129
129
130
130
131 check caching
131 check caching
132
132
133 $ hg co 0
133 $ hg co 0
134 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
134 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
135 $ hg debugsub
135 $ hg debugsub
136
136
137 restore
137 restore
138
138
139 $ hg co
139 $ hg co
140 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
140 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
141 $ hg debugsub
141 $ hg debugsub
142 path s
142 path s
143 source s
143 source s
144 revision 02dcf1d704118aee3ee306ccfa1910850d5b05ef
144 revision 02dcf1d704118aee3ee306ccfa1910850d5b05ef
145
145
146 new branch for merge tests
146 new branch for merge tests
147
147
148 $ hg co 1
148 $ hg co 1
149 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
149 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
150 $ echo t = t >> .hgsub
150 $ echo t = t >> .hgsub
151 $ hg init t
151 $ hg init t
152 $ echo t > t/t
152 $ echo t > t/t
153 $ hg -R t add t
153 $ hg -R t add t
154 adding t/t (glob)
154 adding t/t (glob)
155
155
156 5
156 5
157
157
158 $ hg ci -m5 # add sub
158 $ hg ci -m5 # add sub
159 committing subrepository t
159 committing subrepository t
160 created new head
160 created new head
161 $ echo t2 > t/t
161 $ echo t2 > t/t
162
162
163 6
163 6
164
164
165 $ hg st -R s
165 $ hg st -R s
166 $ hg ci -m6 # change sub
166 $ hg ci -m6 # change sub
167 committing subrepository t
167 committing subrepository t
168 $ hg debugsub
168 $ hg debugsub
169 path s
169 path s
170 source s
170 source s
171 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
171 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
172 path t
172 path t
173 source t
173 source t
174 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
174 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
175 $ echo t3 > t/t
175 $ echo t3 > t/t
176
176
177 7
177 7
178
178
179 $ hg ci -m7 # change sub again for conflict test
179 $ hg ci -m7 # change sub again for conflict test
180 committing subrepository t
180 committing subrepository t
181 $ hg rm .hgsub
181 $ hg rm .hgsub
182
182
183 8
183 8
184
184
185 $ hg ci -m8 # remove sub
185 $ hg ci -m8 # remove sub
186
186
187 merge tests
187 merge tests
188
188
189 $ hg co -C 3
189 $ hg co -C 3
190 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
190 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
191 $ hg merge 5 # test adding
191 $ hg merge 5 # test adding
192 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
192 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
193 (branch merge, don't forget to commit)
193 (branch merge, don't forget to commit)
194 $ hg debugsub
194 $ hg debugsub
195 path s
195 path s
196 source s
196 source s
197 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
197 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
198 path t
198 path t
199 source t
199 source t
200 revision 60ca1237c19474e7a3978b0dc1ca4e6f36d51382
200 revision 60ca1237c19474e7a3978b0dc1ca4e6f36d51382
201 $ hg ci -m9
201 $ hg ci -m9
202 created new head
202 created new head
203 $ hg merge 6 --debug # test change
203 $ hg merge 6 --debug # test change
204 searching for copies back to rev 2
204 searching for copies back to rev 2
205 resolving manifests
205 resolving manifests
206 overwrite: False, partial: False
206 overwrite: False, partial: False
207 ancestor: 1f14a2e2d3ec, local: f0d2028bf86d+, remote: 1831e14459c4
207 ancestor: 1f14a2e2d3ec, local: f0d2028bf86d+, remote: 1831e14459c4
208 .hgsubstate: versions differ -> m
208 .hgsubstate: versions differ -> m
209 updating: .hgsubstate 1/1 files (100.00%)
209 updating: .hgsubstate 1/1 files (100.00%)
210 subrepo merge f0d2028bf86d+ 1831e14459c4 1f14a2e2d3ec
210 subrepo merge f0d2028bf86d+ 1831e14459c4 1f14a2e2d3ec
211 subrepo t: other changed, get t:6747d179aa9a688023c4b0cad32e4c92bb7f34ad:hg
211 subrepo t: other changed, get t:6747d179aa9a688023c4b0cad32e4c92bb7f34ad:hg
212 getting subrepo t
212 getting subrepo t
213 searching for copies back to rev 1
213 searching for copies back to rev 1
214 resolving manifests
214 resolving manifests
215 overwrite: False, partial: False
215 overwrite: False, partial: False
216 ancestor: 60ca1237c194, local: 60ca1237c194+, remote: 6747d179aa9a
216 ancestor: 60ca1237c194, local: 60ca1237c194+, remote: 6747d179aa9a
217 t: remote is newer -> g
217 t: remote is newer -> g
218 updating: t 1/1 files (100.00%)
218 updating: t 1/1 files (100.00%)
219 getting t
219 getting t
220 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
220 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
221 (branch merge, don't forget to commit)
221 (branch merge, don't forget to commit)
222 $ hg debugsub
222 $ hg debugsub
223 path s
223 path s
224 source s
224 source s
225 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
225 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
226 path t
226 path t
227 source t
227 source t
228 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
228 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
229 $ echo conflict > t/t
229 $ echo conflict > t/t
230 $ hg ci -m10
230 $ hg ci -m10
231 committing subrepository t
231 committing subrepository t
232 $ HGMERGE=internal:merge hg merge --debug 7 # test conflict
232 $ HGMERGE=internal:merge hg merge --debug 7 # test conflict
233 searching for copies back to rev 2
233 searching for copies back to rev 2
234 resolving manifests
234 resolving manifests
235 overwrite: False, partial: False
235 overwrite: False, partial: False
236 ancestor: 1831e14459c4, local: e45c8b14af55+, remote: f94576341bcf
236 ancestor: 1831e14459c4, local: e45c8b14af55+, remote: f94576341bcf
237 .hgsubstate: versions differ -> m
237 .hgsubstate: versions differ -> m
238 updating: .hgsubstate 1/1 files (100.00%)
238 updating: .hgsubstate 1/1 files (100.00%)
239 subrepo merge e45c8b14af55+ f94576341bcf 1831e14459c4
239 subrepo merge e45c8b14af55+ f94576341bcf 1831e14459c4
240 subrepo t: both sides changed, merge with t:7af322bc1198a32402fe903e0b7ebcfc5c9bf8f4:hg
240 subrepo t: both sides changed, merge with t:7af322bc1198a32402fe903e0b7ebcfc5c9bf8f4:hg
241 merging subrepo t
241 merging subrepo t
242 searching for copies back to rev 2
242 searching for copies back to rev 2
243 resolving manifests
243 resolving manifests
244 overwrite: False, partial: False
244 overwrite: False, partial: False
245 ancestor: 6747d179aa9a, local: 20a0db6fbf6c+, remote: 7af322bc1198
245 ancestor: 6747d179aa9a, local: 20a0db6fbf6c+, remote: 7af322bc1198
246 t: versions differ -> m
246 t: versions differ -> m
247 preserving t for resolve of t
247 preserving t for resolve of t
248 updating: t 1/1 files (100.00%)
248 updating: t 1/1 files (100.00%)
249 picked tool 'internal:merge' for t (binary False symlink False)
249 picked tool 'internal:merge' for t (binary False symlink False)
250 merging t
250 merging t
251 my t@20a0db6fbf6c+ other t@7af322bc1198 ancestor t@6747d179aa9a
251 my t@20a0db6fbf6c+ other t@7af322bc1198 ancestor t@6747d179aa9a
252 warning: conflicts during merge.
252 warning: conflicts during merge.
253 merging t incomplete! (edit conflicts, then use 'hg resolve --mark')
253 merging t incomplete! (edit conflicts, then use 'hg resolve --mark')
254 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
254 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
255 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
255 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
256 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
256 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
257 (branch merge, don't forget to commit)
257 (branch merge, don't forget to commit)
258
258
259 should conflict
259 should conflict
260
260
261 $ cat t/t
261 $ cat t/t
262 <<<<<<< local
262 <<<<<<< local
263 conflict
263 conflict
264 =======
264 =======
265 t3
265 t3
266 >>>>>>> other
266 >>>>>>> other
267
267
268 clone
268 clone
269
269
270 $ cd ..
270 $ cd ..
271 $ hg clone t tc
271 $ hg clone t tc
272 updating to branch default
272 updating to branch default
273 cloning subrepo s from $TESTTMP/t/s (glob)
273 cloning subrepo s from $TESTTMP/t/s (glob)
274 cloning subrepo s/ss from $TESTTMP/t/s/ss (glob)
274 cloning subrepo s/ss from $TESTTMP/t/s/ss (glob)
275 cloning subrepo t from $TESTTMP/t/t (glob)
275 cloning subrepo t from $TESTTMP/t/t (glob)
276 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
276 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
277 $ cd tc
277 $ cd tc
278 $ hg debugsub
278 $ hg debugsub
279 path s
279 path s
280 source s
280 source s
281 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
281 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
282 path t
282 path t
283 source t
283 source t
284 revision 20a0db6fbf6c3d2836e6519a642ae929bfc67c0e
284 revision 20a0db6fbf6c3d2836e6519a642ae929bfc67c0e
285
285
286 push
286 push
287
287
288 $ echo bah > t/t
288 $ echo bah > t/t
289 $ hg ci -m11
289 $ hg ci -m11
290 committing subrepository t
290 committing subrepository t
291 $ hg push
291 $ hg push
292 pushing to $TESTTMP/t (glob)
292 pushing to $TESTTMP/t (glob)
293 pushing subrepo s/ss to $TESTTMP/t/s/ss (glob)
293 pushing subrepo s/ss to $TESTTMP/t/s/ss (glob)
294 searching for changes
294 searching for changes
295 no changes found
295 no changes found
296 pushing subrepo s to $TESTTMP/t/s (glob)
296 pushing subrepo s to $TESTTMP/t/s (glob)
297 searching for changes
297 searching for changes
298 no changes found
298 no changes found
299 pushing subrepo t to $TESTTMP/t/t (glob)
299 pushing subrepo t to $TESTTMP/t/t (glob)
300 searching for changes
300 searching for changes
301 adding changesets
301 adding changesets
302 adding manifests
302 adding manifests
303 adding file changes
303 adding file changes
304 added 1 changesets with 1 changes to 1 files
304 added 1 changesets with 1 changes to 1 files
305 searching for changes
305 searching for changes
306 adding changesets
306 adding changesets
307 adding manifests
307 adding manifests
308 adding file changes
308 adding file changes
309 added 1 changesets with 1 changes to 1 files
309 added 1 changesets with 1 changes to 1 files
310
310
311 push -f
311 push -f
312
312
313 $ echo bah > s/a
313 $ echo bah > s/a
314 $ hg ci -m12
314 $ hg ci -m12
315 committing subrepository s
315 committing subrepository s
316 $ hg push
316 $ hg push
317 pushing to $TESTTMP/t (glob)
317 pushing to $TESTTMP/t (glob)
318 pushing subrepo s/ss to $TESTTMP/t/s/ss (glob)
318 pushing subrepo s/ss to $TESTTMP/t/s/ss (glob)
319 searching for changes
319 searching for changes
320 no changes found
320 no changes found
321 pushing subrepo s to $TESTTMP/t/s (glob)
321 pushing subrepo s to $TESTTMP/t/s (glob)
322 searching for changes
322 searching for changes
323 abort: push creates new remote head 12a213df6fa9! (in subrepo s)
323 abort: push creates new remote head 12a213df6fa9! (in subrepo s)
324 (did you forget to merge? use push -f to force)
324 (did you forget to merge? use push -f to force)
325 [255]
325 [255]
326 $ hg push -f
326 $ hg push -f
327 pushing to $TESTTMP/t (glob)
327 pushing to $TESTTMP/t (glob)
328 pushing subrepo s/ss to $TESTTMP/t/s/ss (glob)
328 pushing subrepo s/ss to $TESTTMP/t/s/ss (glob)
329 searching for changes
329 searching for changes
330 no changes found
330 no changes found
331 pushing subrepo s to $TESTTMP/t/s (glob)
331 pushing subrepo s to $TESTTMP/t/s (glob)
332 searching for changes
332 searching for changes
333 adding changesets
333 adding changesets
334 adding manifests
334 adding manifests
335 adding file changes
335 adding file changes
336 added 1 changesets with 1 changes to 1 files (+1 heads)
336 added 1 changesets with 1 changes to 1 files (+1 heads)
337 pushing subrepo t to $TESTTMP/t/t (glob)
337 pushing subrepo t to $TESTTMP/t/t (glob)
338 searching for changes
338 searching for changes
339 no changes found
339 no changes found
340 searching for changes
340 searching for changes
341 adding changesets
341 adding changesets
342 adding manifests
342 adding manifests
343 adding file changes
343 adding file changes
344 added 1 changesets with 1 changes to 1 files
344 added 1 changesets with 1 changes to 1 files
345
345
346 update
346 update
347
347
348 $ cd ../t
348 $ cd ../t
349 $ hg up -C # discard our earlier merge
349 $ hg up -C # discard our earlier merge
350 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
350 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
351 $ echo blah > t/t
351 $ echo blah > t/t
352 $ hg ci -m13
352 $ hg ci -m13
353 committing subrepository t
353 committing subrepository t
354
354
355 pull
355 pull
356
356
357 $ cd ../tc
357 $ cd ../tc
358 $ hg pull
358 $ hg pull
359 pulling from $TESTTMP/t (glob)
359 pulling from $TESTTMP/t (glob)
360 searching for changes
360 searching for changes
361 adding changesets
361 adding changesets
362 adding manifests
362 adding manifests
363 adding file changes
363 adding file changes
364 added 1 changesets with 1 changes to 1 files
364 added 1 changesets with 1 changes to 1 files
365 (run 'hg update' to get a working copy)
365 (run 'hg update' to get a working copy)
366
366
367 should pull t
367 should pull t
368
368
369 $ hg up
369 $ hg up
370 pulling subrepo t from $TESTTMP/t/t (glob)
370 pulling subrepo t from $TESTTMP/t/t (glob)
371 searching for changes
371 searching for changes
372 adding changesets
372 adding changesets
373 adding manifests
373 adding manifests
374 adding file changes
374 adding file changes
375 added 1 changesets with 1 changes to 1 files
375 added 1 changesets with 1 changes to 1 files
376 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
376 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
377 $ cat t/t
377 $ cat t/t
378 blah
378 blah
379
379
380 bogus subrepo path aborts
380 bogus subrepo path aborts
381
381
382 $ echo 'bogus=[boguspath' >> .hgsub
382 $ echo 'bogus=[boguspath' >> .hgsub
383 $ hg ci -m 'bogus subrepo path'
383 $ hg ci -m 'bogus subrepo path'
384 abort: missing ] in subrepo source
384 abort: missing ] in subrepo source
385 [255]
385 [255]
386
386
387 Issue1986: merge aborts when trying to merge a subrepo that
387 Issue1986: merge aborts when trying to merge a subrepo that
388 shouldn't need merging
388 shouldn't need merging
389
389
390 # subrepo layout
390 # subrepo layout
391 #
391 #
392 # o 5 br
392 # o 5 br
393 # /|
393 # /|
394 # o | 4 default
394 # o | 4 default
395 # | |
395 # | |
396 # | o 3 br
396 # | o 3 br
397 # |/|
397 # |/|
398 # o | 2 default
398 # o | 2 default
399 # | |
399 # | |
400 # | o 1 br
400 # | o 1 br
401 # |/
401 # |/
402 # o 0 default
402 # o 0 default
403
403
404 $ cd ..
404 $ cd ..
405 $ rm -rf sub
405 $ rm -rf sub
406 $ hg init main
406 $ hg init main
407 $ cd main
407 $ cd main
408 $ hg init s
408 $ hg init s
409 $ cd s
409 $ cd s
410 $ echo a > a
410 $ echo a > a
411 $ hg ci -Am1
411 $ hg ci -Am1
412 adding a
412 adding a
413 $ hg branch br
413 $ hg branch br
414 marked working directory as branch br
414 marked working directory as branch br
415 (branches are permanent and global, did you want a bookmark?)
415 (branches are permanent and global, did you want a bookmark?)
416 $ echo a >> a
416 $ echo a >> a
417 $ hg ci -m1
417 $ hg ci -m1
418 $ hg up default
418 $ hg up default
419 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
419 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
420 $ echo b > b
420 $ echo b > b
421 $ hg ci -Am1
421 $ hg ci -Am1
422 adding b
422 adding b
423 $ hg up br
423 $ hg up br
424 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
424 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
425 $ hg merge tip
425 $ hg merge tip
426 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
426 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
427 (branch merge, don't forget to commit)
427 (branch merge, don't forget to commit)
428 $ hg ci -m1
428 $ hg ci -m1
429 $ hg up 2
429 $ hg up 2
430 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
430 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
431 $ echo c > c
431 $ echo c > c
432 $ hg ci -Am1
432 $ hg ci -Am1
433 adding c
433 adding c
434 $ hg up 3
434 $ hg up 3
435 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
435 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
436 $ hg merge 4
436 $ hg merge 4
437 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
437 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
438 (branch merge, don't forget to commit)
438 (branch merge, don't forget to commit)
439 $ hg ci -m1
439 $ hg ci -m1
440
440
441 # main repo layout:
441 # main repo layout:
442 #
442 #
443 # * <-- try to merge default into br again
443 # * <-- try to merge default into br again
444 # .`|
444 # .`|
445 # . o 5 br --> substate = 5
445 # . o 5 br --> substate = 5
446 # . |
446 # . |
447 # o | 4 default --> substate = 4
447 # o | 4 default --> substate = 4
448 # | |
448 # | |
449 # | o 3 br --> substate = 2
449 # | o 3 br --> substate = 2
450 # |/|
450 # |/|
451 # o | 2 default --> substate = 2
451 # o | 2 default --> substate = 2
452 # | |
452 # | |
453 # | o 1 br --> substate = 3
453 # | o 1 br --> substate = 3
454 # |/
454 # |/
455 # o 0 default --> substate = 2
455 # o 0 default --> substate = 2
456
456
457 $ cd ..
457 $ cd ..
458 $ echo 's = s' > .hgsub
458 $ echo 's = s' > .hgsub
459 $ hg -R s up 2
459 $ hg -R s up 2
460 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
460 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
461 $ hg ci -Am1
461 $ hg ci -Am1
462 adding .hgsub
462 adding .hgsub
463 $ hg branch br
463 $ hg branch br
464 marked working directory as branch br
464 marked working directory as branch br
465 (branches are permanent and global, did you want a bookmark?)
465 (branches are permanent and global, did you want a bookmark?)
466 $ echo b > b
466 $ echo b > b
467 $ hg -R s up 3
467 $ hg -R s up 3
468 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
468 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
469 $ hg ci -Am1
469 $ hg ci -Am1
470 adding b
470 adding b
471 $ hg up default
471 $ hg up default
472 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
472 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
473 $ echo c > c
473 $ echo c > c
474 $ hg ci -Am1
474 $ hg ci -Am1
475 adding c
475 adding c
476 $ hg up 1
476 $ hg up 1
477 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
477 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
478 $ hg merge 2
478 $ hg merge 2
479 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
479 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
480 (branch merge, don't forget to commit)
480 (branch merge, don't forget to commit)
481 $ hg ci -m1
481 $ hg ci -m1
482 $ hg up 2
482 $ hg up 2
483 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
483 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
484 $ hg -R s up 4
484 $ hg -R s up 4
485 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
485 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
486 $ echo d > d
486 $ echo d > d
487 $ hg ci -Am1
487 $ hg ci -Am1
488 adding d
488 adding d
489 $ hg up 3
489 $ hg up 3
490 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
490 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
491 $ hg -R s up 5
491 $ hg -R s up 5
492 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
492 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
493 $ echo e > e
493 $ echo e > e
494 $ hg ci -Am1
494 $ hg ci -Am1
495 adding e
495 adding e
496
496
497 $ hg up 5
497 $ hg up 5
498 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
498 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
499 $ hg merge 4 # try to merge default into br again
499 $ hg merge 4 # try to merge default into br again
500 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
500 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
501 (branch merge, don't forget to commit)
501 (branch merge, don't forget to commit)
502 $ cd ..
502 $ cd ..
503
503
504 test subrepo delete from .hgsubstate
504 test subrepo delete from .hgsubstate
505
505
506 $ hg init testdelete
506 $ hg init testdelete
507 $ mkdir testdelete/nested testdelete/nested2
507 $ mkdir testdelete/nested testdelete/nested2
508 $ hg init testdelete/nested
508 $ hg init testdelete/nested
509 $ hg init testdelete/nested2
509 $ hg init testdelete/nested2
510 $ echo test > testdelete/nested/foo
510 $ echo test > testdelete/nested/foo
511 $ echo test > testdelete/nested2/foo
511 $ echo test > testdelete/nested2/foo
512 $ hg -R testdelete/nested add
512 $ hg -R testdelete/nested add
513 adding testdelete/nested/foo (glob)
513 adding testdelete/nested/foo (glob)
514 $ hg -R testdelete/nested2 add
514 $ hg -R testdelete/nested2 add
515 adding testdelete/nested2/foo (glob)
515 adding testdelete/nested2/foo (glob)
516 $ hg -R testdelete/nested ci -m test
516 $ hg -R testdelete/nested ci -m test
517 $ hg -R testdelete/nested2 ci -m test
517 $ hg -R testdelete/nested2 ci -m test
518 $ echo nested = nested > testdelete/.hgsub
518 $ echo nested = nested > testdelete/.hgsub
519 $ echo nested2 = nested2 >> testdelete/.hgsub
519 $ echo nested2 = nested2 >> testdelete/.hgsub
520 $ hg -R testdelete add
520 $ hg -R testdelete add
521 adding testdelete/.hgsub (glob)
521 adding testdelete/.hgsub (glob)
522 $ hg -R testdelete ci -m "nested 1 & 2 added"
522 $ hg -R testdelete ci -m "nested 1 & 2 added"
523 $ echo nested = nested > testdelete/.hgsub
523 $ echo nested = nested > testdelete/.hgsub
524 $ hg -R testdelete ci -m "nested 2 deleted"
524 $ hg -R testdelete ci -m "nested 2 deleted"
525 $ cat testdelete/.hgsubstate
525 $ cat testdelete/.hgsubstate
526 bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
526 bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
527 $ hg -R testdelete remove testdelete/.hgsub
527 $ hg -R testdelete remove testdelete/.hgsub
528 $ hg -R testdelete ci -m ".hgsub deleted"
528 $ hg -R testdelete ci -m ".hgsub deleted"
529 $ cat testdelete/.hgsubstate
529 $ cat testdelete/.hgsubstate
530 bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
530 bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
531
531
532 test repository cloning
532 test repository cloning
533
533
534 $ mkdir mercurial mercurial2
534 $ mkdir mercurial mercurial2
535 $ hg init nested_absolute
535 $ hg init nested_absolute
536 $ echo test > nested_absolute/foo
536 $ echo test > nested_absolute/foo
537 $ hg -R nested_absolute add
537 $ hg -R nested_absolute add
538 adding nested_absolute/foo (glob)
538 adding nested_absolute/foo (glob)
539 $ hg -R nested_absolute ci -mtest
539 $ hg -R nested_absolute ci -mtest
540 $ cd mercurial
540 $ cd mercurial
541 $ hg init nested_relative
541 $ hg init nested_relative
542 $ echo test2 > nested_relative/foo2
542 $ echo test2 > nested_relative/foo2
543 $ hg -R nested_relative add
543 $ hg -R nested_relative add
544 adding nested_relative/foo2 (glob)
544 adding nested_relative/foo2 (glob)
545 $ hg -R nested_relative ci -mtest2
545 $ hg -R nested_relative ci -mtest2
546 $ hg init main
546 $ hg init main
547 $ echo "nested_relative = ../nested_relative" > main/.hgsub
547 $ echo "nested_relative = ../nested_relative" > main/.hgsub
548 $ echo "nested_absolute = `pwd`/nested_absolute" >> main/.hgsub
548 $ echo "nested_absolute = `pwd`/nested_absolute" >> main/.hgsub
549 $ hg -R main add
549 $ hg -R main add
550 adding main/.hgsub (glob)
550 adding main/.hgsub (glob)
551 $ hg -R main ci -m "add subrepos"
551 $ hg -R main ci -m "add subrepos"
552 $ cd ..
552 $ cd ..
553 $ hg clone mercurial/main mercurial2/main
553 $ hg clone mercurial/main mercurial2/main
554 updating to branch default
554 updating to branch default
555 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
555 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
556 $ cat mercurial2/main/nested_absolute/.hg/hgrc \
556 $ cat mercurial2/main/nested_absolute/.hg/hgrc \
557 > mercurial2/main/nested_relative/.hg/hgrc
557 > mercurial2/main/nested_relative/.hg/hgrc
558 [paths]
558 [paths]
559 default = $TESTTMP/mercurial/nested_absolute
559 default = $TESTTMP/mercurial/nested_absolute
560 [paths]
560 [paths]
561 default = $TESTTMP/mercurial/nested_relative
561 default = $TESTTMP/mercurial/nested_relative
562 $ rm -rf mercurial mercurial2
562 $ rm -rf mercurial mercurial2
563
563
564 Issue1977: multirepo push should fail if subrepo push fails
564 Issue1977: multirepo push should fail if subrepo push fails
565
565
566 $ hg init repo
566 $ hg init repo
567 $ hg init repo/s
567 $ hg init repo/s
568 $ echo a > repo/s/a
568 $ echo a > repo/s/a
569 $ hg -R repo/s ci -Am0
569 $ hg -R repo/s ci -Am0
570 adding a
570 adding a
571 $ echo s = s > repo/.hgsub
571 $ echo s = s > repo/.hgsub
572 $ hg -R repo ci -Am1
572 $ hg -R repo ci -Am1
573 adding .hgsub
573 adding .hgsub
574 $ hg clone repo repo2
574 $ hg clone repo repo2
575 updating to branch default
575 updating to branch default
576 cloning subrepo s from $TESTTMP/repo/s (glob)
576 cloning subrepo s from $TESTTMP/repo/s (glob)
577 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
577 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
578 $ hg -q -R repo2 pull -u
578 $ hg -q -R repo2 pull -u
579 $ echo 1 > repo2/s/a
579 $ echo 1 > repo2/s/a
580 $ hg -R repo2/s ci -m2
580 $ hg -R repo2/s ci -m2
581 $ hg -q -R repo2/s push
581 $ hg -q -R repo2/s push
582 $ hg -R repo2/s up -C 0
582 $ hg -R repo2/s up -C 0
583 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
583 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
584 $ echo 2 > repo2/s/b
584 $ echo 2 > repo2/s/b
585 $ hg -R repo2/s ci -m3 -A
585 $ hg -R repo2/s ci -m3 -A
586 adding b
586 adding b
587 created new head
587 created new head
588 $ hg -R repo2 ci -m3
588 $ hg -R repo2 ci -m3
589 $ hg -q -R repo2 push
589 $ hg -q -R repo2 push
590 abort: push creates new remote head cc505f09a8b2! (in subrepo s)
590 abort: push creates new remote head cc505f09a8b2! (in subrepo s)
591 (did you forget to merge? use push -f to force)
591 (did you forget to merge? use push -f to force)
592 [255]
592 [255]
593 $ hg -R repo update
593 $ hg -R repo update
594 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
594 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
595
595
596 test if untracked file is not overwritten
596 test if untracked file is not overwritten
597
597
598 $ echo issue3276_ok > repo/s/b
598 $ echo issue3276_ok > repo/s/b
599 $ hg -R repo2 push -f -q
599 $ hg -R repo2 push -f -q
600 $ hg -R repo update
600 $ hg -R repo update
601 b: untracked file differs
601 b: untracked file differs
602 abort: untracked files in working directory differ from files in requested revision (in subrepo s)
602 abort: untracked files in working directory differ from files in requested revision (in subrepo s)
603 [255]
603 [255]
604
604
605 $ cat repo/s/b
605 $ cat repo/s/b
606 issue3276_ok
606 issue3276_ok
607 $ rm repo/s/b
607 $ rm repo/s/b
608 $ hg -R repo revert --all
608 $ hg -R repo revert --all
609 reverting repo/.hgsubstate (glob)
609 reverting repo/.hgsubstate (glob)
610 reverting subrepo s
610 reverting subrepo s
611 $ hg -R repo update
611 $ hg -R repo update
612 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
612 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
613 $ cat repo/s/b
613 $ cat repo/s/b
614 2
614 2
615 $ rm -rf repo2 repo
615 $ rm -rf repo2 repo
616
616
617
617
618 Issue1852 subrepos with relative paths always push/pull relative to default
618 Issue1852 subrepos with relative paths always push/pull relative to default
619
619
620 Prepare a repo with subrepo
620 Prepare a repo with subrepo
621
621
622 $ hg init issue1852a
622 $ hg init issue1852a
623 $ cd issue1852a
623 $ cd issue1852a
624 $ hg init sub/repo
624 $ hg init sub/repo
625 $ echo test > sub/repo/foo
625 $ echo test > sub/repo/foo
626 $ hg -R sub/repo add sub/repo/foo
626 $ hg -R sub/repo add sub/repo/foo
627 $ echo sub/repo = sub/repo > .hgsub
627 $ echo sub/repo = sub/repo > .hgsub
628 $ hg add .hgsub
628 $ hg add .hgsub
629 $ hg ci -mtest
629 $ hg ci -mtest
630 committing subrepository sub/repo (glob)
630 committing subrepository sub/repo (glob)
631 $ echo test >> sub/repo/foo
631 $ echo test >> sub/repo/foo
632 $ hg ci -mtest
632 $ hg ci -mtest
633 committing subrepository sub/repo (glob)
633 committing subrepository sub/repo (glob)
634 $ cd ..
634 $ cd ..
635
635
636 Create repo without default path, pull top repo, and see what happens on update
636 Create repo without default path, pull top repo, and see what happens on update
637
637
638 $ hg init issue1852b
638 $ hg init issue1852b
639 $ hg -R issue1852b pull issue1852a
639 $ hg -R issue1852b pull issue1852a
640 pulling from issue1852a
640 pulling from issue1852a
641 requesting all changes
641 requesting all changes
642 adding changesets
642 adding changesets
643 adding manifests
643 adding manifests
644 adding file changes
644 adding file changes
645 added 2 changesets with 3 changes to 2 files
645 added 2 changesets with 3 changes to 2 files
646 (run 'hg update' to get a working copy)
646 (run 'hg update' to get a working copy)
647 $ hg -R issue1852b update
647 $ hg -R issue1852b update
648 abort: default path for subrepository not found (in subrepo sub/repo) (glob)
648 abort: default path for subrepository not found (in subrepo sub/repo) (glob)
649 [255]
649 [255]
650
650
651 Pull -u now doesn't help
651 Pull -u now doesn't help
652
652
653 $ hg -R issue1852b pull -u issue1852a
653 $ hg -R issue1852b pull -u issue1852a
654 pulling from issue1852a
654 pulling from issue1852a
655 searching for changes
655 searching for changes
656 no changes found
656 no changes found
657
657
658 Try the same, but with pull -u
658 Try the same, but with pull -u
659
659
660 $ hg init issue1852c
660 $ hg init issue1852c
661 $ hg -R issue1852c pull -r0 -u issue1852a
661 $ hg -R issue1852c pull -r0 -u issue1852a
662 pulling from issue1852a
662 pulling from issue1852a
663 adding changesets
663 adding changesets
664 adding manifests
664 adding manifests
665 adding file changes
665 adding file changes
666 added 1 changesets with 2 changes to 2 files
666 added 1 changesets with 2 changes to 2 files
667 cloning subrepo sub/repo from issue1852a/sub/repo (glob)
667 cloning subrepo sub/repo from issue1852a/sub/repo (glob)
668 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
668 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
669
669
670 Try to push from the other side
670 Try to push from the other side
671
671
672 $ hg -R issue1852a push `pwd`/issue1852c
672 $ hg -R issue1852a push `pwd`/issue1852c
673 pushing to $TESTTMP/issue1852c
673 pushing to $TESTTMP/issue1852c
674 pushing subrepo sub/repo to $TESTTMP/issue1852c/sub/repo (glob)
674 pushing subrepo sub/repo to $TESTTMP/issue1852c/sub/repo (glob)
675 searching for changes
675 searching for changes
676 no changes found
676 no changes found
677 searching for changes
677 searching for changes
678 adding changesets
678 adding changesets
679 adding manifests
679 adding manifests
680 adding file changes
680 adding file changes
681 added 1 changesets with 1 changes to 1 files
681 added 1 changesets with 1 changes to 1 files
682
682
683 Incoming and outgoing should not use the default path:
683 Incoming and outgoing should not use the default path:
684
684
685 $ hg clone -q issue1852a issue1852d
685 $ hg clone -q issue1852a issue1852d
686 $ hg -R issue1852d outgoing --subrepos issue1852c
686 $ hg -R issue1852d outgoing --subrepos issue1852c
687 comparing with issue1852c
687 comparing with issue1852c
688 searching for changes
688 searching for changes
689 no changes found
689 no changes found
690 comparing with issue1852c/sub/repo
690 comparing with issue1852c/sub/repo
691 searching for changes
691 searching for changes
692 no changes found
692 no changes found
693 [1]
693 [1]
694 $ hg -R issue1852d incoming --subrepos issue1852c
694 $ hg -R issue1852d incoming --subrepos issue1852c
695 comparing with issue1852c
695 comparing with issue1852c
696 searching for changes
696 searching for changes
697 no changes found
697 no changes found
698 comparing with issue1852c/sub/repo
698 comparing with issue1852c/sub/repo
699 searching for changes
699 searching for changes
700 no changes found
700 no changes found
701 [1]
701 [1]
702
702
703 Check status of files when none of them belong to the first
703 Check status of files when none of them belong to the first
704 subrepository:
704 subrepository:
705
705
706 $ hg init subrepo-status
706 $ hg init subrepo-status
707 $ cd subrepo-status
707 $ cd subrepo-status
708 $ hg init subrepo-1
708 $ hg init subrepo-1
709 $ hg init subrepo-2
709 $ hg init subrepo-2
710 $ cd subrepo-2
710 $ cd subrepo-2
711 $ touch file
711 $ touch file
712 $ hg add file
712 $ hg add file
713 $ cd ..
713 $ cd ..
714 $ echo subrepo-1 = subrepo-1 > .hgsub
714 $ echo subrepo-1 = subrepo-1 > .hgsub
715 $ echo subrepo-2 = subrepo-2 >> .hgsub
715 $ echo subrepo-2 = subrepo-2 >> .hgsub
716 $ hg add .hgsub
716 $ hg add .hgsub
717 $ hg ci -m 'Added subrepos'
717 $ hg ci -m 'Added subrepos'
718 committing subrepository subrepo-2
718 committing subrepository subrepo-2
719 $ hg st subrepo-2/file
719 $ hg st subrepo-2/file
720
720
721 Check that share works with subrepo
721 Check that share works with subrepo
722 $ hg --config extensions.share= share . ../shared
722 $ hg --config extensions.share= share . ../shared
723 updating working directory
723 updating working directory
724 cloning subrepo subrepo-2 from $TESTTMP/subrepo-status/subrepo-2
724 cloning subrepo subrepo-2 from $TESTTMP/subrepo-status/subrepo-2
725 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
725 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
726 $ test -f ../shared/subrepo-1/.hg/sharedpath
726 $ test -f ../shared/subrepo-1/.hg/sharedpath
727 [1]
727 [1]
728 $ hg -R ../shared in
728 $ hg -R ../shared in
729 abort: repository default not found!
729 abort: repository default not found!
730 [255]
730 [255]
731 $ hg -R ../shared/subrepo-2 showconfig paths
731 $ hg -R ../shared/subrepo-2 showconfig paths
732 paths.default=$TESTTMP/subrepo-status/subrepo-2
732 paths.default=$TESTTMP/subrepo-status/subrepo-2
733 $ hg -R ../shared/subrepo-1 sum --remote
733 $ hg -R ../shared/subrepo-1 sum --remote
734 parent: -1:000000000000 tip (empty repository)
734 parent: -1:000000000000 tip (empty repository)
735 branch: default
735 branch: default
736 commit: (clean)
736 commit: (clean)
737 update: (current)
737 update: (current)
738 remote: (synced)
738 remote: (synced)
739
739
740 Check hg update --clean
740 Check hg update --clean
741 $ cd $TESTTMP/t
741 $ cd $TESTTMP/t
742 $ rm -r t/t.orig
742 $ rm -r t/t.orig
743 $ hg status -S --all
743 $ hg status -S --all
744 C .hgsub
744 C .hgsub
745 C .hgsubstate
745 C .hgsubstate
746 C a
746 C a
747 C s/.hgsub
747 C s/.hgsub
748 C s/.hgsubstate
748 C s/.hgsubstate
749 C s/a
749 C s/a
750 C s/ss/a
750 C s/ss/a
751 C t/t
751 C t/t
752 $ echo c1 > s/a
752 $ echo c1 > s/a
753 $ cd s
753 $ cd s
754 $ echo c1 > b
754 $ echo c1 > b
755 $ echo c1 > c
755 $ echo c1 > c
756 $ hg add b
756 $ hg add b
757 $ cd ..
757 $ cd ..
758 $ hg status -S
758 $ hg status -S
759 M s/a
759 M s/a
760 A s/b
760 A s/b
761 ? s/c
761 ? s/c
762 $ hg update -C
762 $ hg update -C
763 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
763 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
764 $ hg status -S
764 $ hg status -S
765 ? s/b
765 ? s/b
766 ? s/c
766 ? s/c
767
767
768 Sticky subrepositories, no changes
768 Sticky subrepositories, no changes
769 $ cd $TESTTMP/t
769 $ cd $TESTTMP/t
770 $ hg id
770 $ hg id
771 925c17564ef8 tip
771 925c17564ef8 tip
772 $ hg -R s id
772 $ hg -R s id
773 12a213df6fa9 tip
773 12a213df6fa9 tip
774 $ hg -R t id
774 $ hg -R t id
775 52c0adc0515a tip
775 52c0adc0515a tip
776 $ hg update 11
776 $ hg update 11
777 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
777 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
778 $ hg id
778 $ hg id
779 365661e5936a
779 365661e5936a
780 $ hg -R s id
780 $ hg -R s id
781 fc627a69481f
781 fc627a69481f
782 $ hg -R t id
782 $ hg -R t id
783 e95bcfa18a35
783 e95bcfa18a35
784
784
785 Sticky subrepositorys, file changes
785 Sticky subrepositorys, file changes
786 $ touch s/f1
786 $ touch s/f1
787 $ touch t/f1
787 $ touch t/f1
788 $ hg add -S s/f1
788 $ hg add -S s/f1
789 $ hg add -S t/f1
789 $ hg add -S t/f1
790 $ hg id
790 $ hg id
791 365661e5936a+
791 365661e5936a+
792 $ hg -R s id
792 $ hg -R s id
793 fc627a69481f+
793 fc627a69481f+
794 $ hg -R t id
794 $ hg -R t id
795 e95bcfa18a35+
795 e95bcfa18a35+
796 $ hg update tip
796 $ hg update tip
797 subrepository sources for s differ
797 subrepository sources for s differ
798 use (l)ocal source (fc627a69481f) or (r)emote source (12a213df6fa9)?
798 use (l)ocal source (fc627a69481f) or (r)emote source (12a213df6fa9)?
799 l
799 l
800 subrepository sources for t differ
800 subrepository sources for t differ
801 use (l)ocal source (e95bcfa18a35) or (r)emote source (52c0adc0515a)?
801 use (l)ocal source (e95bcfa18a35) or (r)emote source (52c0adc0515a)?
802 l
802 l
803 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
803 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
804 $ hg id
804 $ hg id
805 925c17564ef8+ tip
805 925c17564ef8+ tip
806 $ hg -R s id
806 $ hg -R s id
807 fc627a69481f+
807 fc627a69481f+
808 $ hg -R t id
808 $ hg -R t id
809 e95bcfa18a35+
809 e95bcfa18a35+
810 $ hg update --clean tip
810 $ hg update --clean tip
811 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
811 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
812
812
813 Sticky subrepository, revision updates
813 Sticky subrepository, revision updates
814 $ hg id
814 $ hg id
815 925c17564ef8 tip
815 925c17564ef8 tip
816 $ hg -R s id
816 $ hg -R s id
817 12a213df6fa9 tip
817 12a213df6fa9 tip
818 $ hg -R t id
818 $ hg -R t id
819 52c0adc0515a tip
819 52c0adc0515a tip
820 $ cd s
820 $ cd s
821 $ hg update -r -2
821 $ hg update -r -2
822 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
822 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
823 $ cd ../t
823 $ cd ../t
824 $ hg update -r 2
824 $ hg update -r 2
825 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
825 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
826 $ cd ..
826 $ cd ..
827 $ hg update 10
827 $ hg update 10
828 subrepository sources for t differ (in checked out version)
828 subrepository sources for t differ (in checked out version)
829 use (l)ocal source (7af322bc1198) or (r)emote source (20a0db6fbf6c)?
829 use (l)ocal source (7af322bc1198) or (r)emote source (20a0db6fbf6c)?
830 l
830 l
831 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
831 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
832 $ hg id
832 $ hg id
833 e45c8b14af55+
833 e45c8b14af55+
834 $ hg -R s id
834 $ hg -R s id
835 02dcf1d70411
835 02dcf1d70411
836 $ hg -R t id
836 $ hg -R t id
837 7af322bc1198
837 7af322bc1198
838
838
839 Sticky subrepository, file changes and revision updates
839 Sticky subrepository, file changes and revision updates
840 $ touch s/f1
840 $ touch s/f1
841 $ touch t/f1
841 $ touch t/f1
842 $ hg add -S s/f1
842 $ hg add -S s/f1
843 $ hg add -S t/f1
843 $ hg add -S t/f1
844 $ hg id
844 $ hg id
845 e45c8b14af55+
845 e45c8b14af55+
846 $ hg -R s id
846 $ hg -R s id
847 02dcf1d70411+
847 02dcf1d70411+
848 $ hg -R t id
848 $ hg -R t id
849 7af322bc1198+
849 7af322bc1198+
850 $ hg update tip
850 $ hg update tip
851 subrepository sources for s differ
851 subrepository sources for s differ
852 use (l)ocal source (02dcf1d70411) or (r)emote source (12a213df6fa9)?
852 use (l)ocal source (02dcf1d70411) or (r)emote source (12a213df6fa9)?
853 l
853 l
854 subrepository sources for t differ
854 subrepository sources for t differ
855 use (l)ocal source (7af322bc1198) or (r)emote source (52c0adc0515a)?
855 use (l)ocal source (7af322bc1198) or (r)emote source (52c0adc0515a)?
856 l
856 l
857 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
857 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
858 $ hg id
858 $ hg id
859 925c17564ef8+ tip
859 925c17564ef8+ tip
860 $ hg -R s id
860 $ hg -R s id
861 02dcf1d70411+
861 02dcf1d70411+
862 $ hg -R t id
862 $ hg -R t id
863 7af322bc1198+
863 7af322bc1198+
864
864
865 Sticky repository, update --clean
865 Sticky repository, update --clean
866 $ hg update --clean tip
866 $ hg update --clean tip
867 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
867 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
868 $ hg id
868 $ hg id
869 925c17564ef8 tip
869 925c17564ef8 tip
870 $ hg -R s id
870 $ hg -R s id
871 12a213df6fa9 tip
871 12a213df6fa9 tip
872 $ hg -R t id
872 $ hg -R t id
873 52c0adc0515a tip
873 52c0adc0515a tip
874
874
875 Test subrepo already at intended revision:
875 Test subrepo already at intended revision:
876 $ cd s
876 $ cd s
877 $ hg update fc627a69481f
877 $ hg update fc627a69481f
878 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
878 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
879 $ cd ..
879 $ cd ..
880 $ hg update 11
880 $ hg update 11
881 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
881 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
882 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
882 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
883 $ hg id -n
883 $ hg id -n
884 11+
884 11+
885 $ hg -R s id
885 $ hg -R s id
886 fc627a69481f
886 fc627a69481f
887 $ hg -R t id
887 $ hg -R t id
888 e95bcfa18a35
888 e95bcfa18a35
889
889
890 Test that removing .hgsubstate doesn't break anything:
890 Test that removing .hgsubstate doesn't break anything:
891
891
892 $ hg rm -f .hgsubstate
892 $ hg rm -f .hgsubstate
893 $ hg ci -mrm
893 $ hg ci -mrm
894 nothing changed
894 nothing changed
895 [1]
895 [1]
896 $ hg log -vr tip
896 $ hg log -vr tip
897 changeset: 13:925c17564ef8
897 changeset: 13:925c17564ef8
898 tag: tip
898 tag: tip
899 user: test
899 user: test
900 date: Thu Jan 01 00:00:00 1970 +0000
900 date: Thu Jan 01 00:00:00 1970 +0000
901 files: .hgsubstate
901 files: .hgsubstate
902 description:
902 description:
903 13
903 13
904
904
905
905
906
906
907 Test that removing .hgsub removes .hgsubstate:
907 Test that removing .hgsub removes .hgsubstate:
908
908
909 $ hg rm .hgsub
909 $ hg rm .hgsub
910 $ hg ci -mrm2
910 $ hg ci -mrm2
911 created new head
911 created new head
912 $ hg log -vr tip
912 $ hg log -vr tip
913 changeset: 14:2400bccd50af
913 changeset: 14:2400bccd50af
914 tag: tip
914 tag: tip
915 parent: 11:365661e5936a
915 parent: 11:365661e5936a
916 user: test
916 user: test
917 date: Thu Jan 01 00:00:00 1970 +0000
917 date: Thu Jan 01 00:00:00 1970 +0000
918 files: .hgsub .hgsubstate
918 files: .hgsub .hgsubstate
919 description:
919 description:
920 rm2
920 rm2
921
921
922
922
923 Test issue3153: diff -S with deleted subrepos
923 Test issue3153: diff -S with deleted subrepos
924
924
925 $ hg diff --nodates -S -c .
925 $ hg diff --nodates -S -c .
926 diff -r 365661e5936a -r 2400bccd50af .hgsub
926 diff -r 365661e5936a -r 2400bccd50af .hgsub
927 --- a/.hgsub
927 --- a/.hgsub
928 +++ /dev/null
928 +++ /dev/null
929 @@ -1,2 +0,0 @@
929 @@ -1,2 +0,0 @@
930 -s = s
930 -s = s
931 -t = t
931 -t = t
932 diff -r 365661e5936a -r 2400bccd50af .hgsubstate
932 diff -r 365661e5936a -r 2400bccd50af .hgsubstate
933 --- a/.hgsubstate
933 --- a/.hgsubstate
934 +++ /dev/null
934 +++ /dev/null
935 @@ -1,2 +0,0 @@
935 @@ -1,2 +0,0 @@
936 -fc627a69481fcbe5f1135069e8a3881c023e4cf5 s
936 -fc627a69481fcbe5f1135069e8a3881c023e4cf5 s
937 -e95bcfa18a358dc4936da981ebf4147b4cad1362 t
937 -e95bcfa18a358dc4936da981ebf4147b4cad1362 t
938
938
939 Test behavior of add for explicit path in subrepo:
939 Test behavior of add for explicit path in subrepo:
940 $ cd ..
940 $ cd ..
941 $ hg init explicit
941 $ hg init explicit
942 $ cd explicit
942 $ cd explicit
943 $ echo s = s > .hgsub
943 $ echo s = s > .hgsub
944 $ hg add .hgsub
944 $ hg add .hgsub
945 $ hg init s
945 $ hg init s
946 $ hg ci -m0
946 $ hg ci -m0
947 Adding with an explicit path in a subrepo adds the file
947 Adding with an explicit path in a subrepo adds the file
948 $ echo c1 > f1
948 $ echo c1 > f1
949 $ echo c2 > s/f2
949 $ echo c2 > s/f2
950 $ hg st -S
950 $ hg st -S
951 ? f1
951 ? f1
952 ? s/f2
952 ? s/f2
953 $ hg add s/f2
953 $ hg add s/f2
954 $ hg st -S
954 $ hg st -S
955 A s/f2
955 A s/f2
956 ? f1
956 ? f1
957 $ hg ci -R s -m0
957 $ hg ci -R s -m0
958 $ hg ci -Am1
958 $ hg ci -Am1
959 adding f1
959 adding f1
960 Adding with an explicit path in a subrepo with -S has the same behavior
960 Adding with an explicit path in a subrepo with -S has the same behavior
961 $ echo c3 > f3
961 $ echo c3 > f3
962 $ echo c4 > s/f4
962 $ echo c4 > s/f4
963 $ hg st -S
963 $ hg st -S
964 ? f3
964 ? f3
965 ? s/f4
965 ? s/f4
966 $ hg add -S s/f4
966 $ hg add -S s/f4
967 $ hg st -S
967 $ hg st -S
968 A s/f4
968 A s/f4
969 ? f3
969 ? f3
970 $ hg ci -R s -m1
970 $ hg ci -R s -m1
971 $ hg ci -Ama2
971 $ hg ci -Ama2
972 adding f3
972 adding f3
973 Adding without a path or pattern silently ignores subrepos
973 Adding without a path or pattern silently ignores subrepos
974 $ echo c5 > f5
974 $ echo c5 > f5
975 $ echo c6 > s/f6
975 $ echo c6 > s/f6
976 $ echo c7 > s/f7
976 $ echo c7 > s/f7
977 $ hg st -S
977 $ hg st -S
978 ? f5
978 ? f5
979 ? s/f6
979 ? s/f6
980 ? s/f7
980 ? s/f7
981 $ hg add
981 $ hg add
982 adding f5
982 adding f5
983 $ hg st -S
983 $ hg st -S
984 A f5
984 A f5
985 ? s/f6
985 ? s/f6
986 ? s/f7
986 ? s/f7
987 $ hg ci -R s -Am2
987 $ hg ci -R s -Am2
988 adding f6
988 adding f6
989 adding f7
989 adding f7
990 $ hg ci -m3
990 $ hg ci -m3
991 Adding without a path or pattern with -S also adds files in subrepos
991 Adding without a path or pattern with -S also adds files in subrepos
992 $ echo c8 > f8
992 $ echo c8 > f8
993 $ echo c9 > s/f9
993 $ echo c9 > s/f9
994 $ echo c10 > s/f10
994 $ echo c10 > s/f10
995 $ hg st -S
995 $ hg st -S
996 ? f8
996 ? f8
997 ? s/f10
997 ? s/f10
998 ? s/f9
998 ? s/f9
999 $ hg add -S
999 $ hg add -S
1000 adding f8
1000 adding f8
1001 adding s/f10 (glob)
1001 adding s/f10 (glob)
1002 adding s/f9 (glob)
1002 adding s/f9 (glob)
1003 $ hg st -S
1003 $ hg st -S
1004 A f8
1004 A f8
1005 A s/f10
1005 A s/f10
1006 A s/f9
1006 A s/f9
1007 $ hg ci -R s -m3
1007 $ hg ci -R s -m3
1008 $ hg ci -m4
1008 $ hg ci -m4
1009 Adding with a pattern silently ignores subrepos
1009 Adding with a pattern silently ignores subrepos
1010 $ echo c11 > fm11
1010 $ echo c11 > fm11
1011 $ echo c12 > fn12
1011 $ echo c12 > fn12
1012 $ echo c13 > s/fm13
1012 $ echo c13 > s/fm13
1013 $ echo c14 > s/fn14
1013 $ echo c14 > s/fn14
1014 $ hg st -S
1014 $ hg st -S
1015 ? fm11
1015 ? fm11
1016 ? fn12
1016 ? fn12
1017 ? s/fm13
1017 ? s/fm13
1018 ? s/fn14
1018 ? s/fn14
1019 $ hg add 'glob:**fm*'
1019 $ hg add 'glob:**fm*'
1020 adding fm11
1020 adding fm11
1021 $ hg st -S
1021 $ hg st -S
1022 A fm11
1022 A fm11
1023 ? fn12
1023 ? fn12
1024 ? s/fm13
1024 ? s/fm13
1025 ? s/fn14
1025 ? s/fn14
1026 $ hg ci -R s -Am4
1026 $ hg ci -R s -Am4
1027 adding fm13
1027 adding fm13
1028 adding fn14
1028 adding fn14
1029 $ hg ci -Am5
1029 $ hg ci -Am5
1030 adding fn12
1030 adding fn12
1031 Adding with a pattern with -S also adds matches in subrepos
1031 Adding with a pattern with -S also adds matches in subrepos
1032 $ echo c15 > fm15
1032 $ echo c15 > fm15
1033 $ echo c16 > fn16
1033 $ echo c16 > fn16
1034 $ echo c17 > s/fm17
1034 $ echo c17 > s/fm17
1035 $ echo c18 > s/fn18
1035 $ echo c18 > s/fn18
1036 $ hg st -S
1036 $ hg st -S
1037 ? fm15
1037 ? fm15
1038 ? fn16
1038 ? fn16
1039 ? s/fm17
1039 ? s/fm17
1040 ? s/fn18
1040 ? s/fn18
1041 $ hg add -S 'glob:**fm*'
1041 $ hg add -S 'glob:**fm*'
1042 adding fm15
1042 adding fm15
1043 adding s/fm17 (glob)
1043 adding s/fm17 (glob)
1044 $ hg st -S
1044 $ hg st -S
1045 A fm15
1045 A fm15
1046 A s/fm17
1046 A s/fm17
1047 ? fn16
1047 ? fn16
1048 ? s/fn18
1048 ? s/fn18
1049 $ hg ci -R s -Am5
1049 $ hg ci -R s -Am5
1050 adding fn18
1050 adding fn18
1051 $ hg ci -Am6
1051 $ hg ci -Am6
1052 adding fn16
1052 adding fn16
1053
1053
1054 Test behavior of forget for explicit path in subrepo:
1054 Test behavior of forget for explicit path in subrepo:
1055 Forgetting an explicit path in a subrepo untracks the file
1055 Forgetting an explicit path in a subrepo untracks the file
1056 $ echo c19 > s/f19
1056 $ echo c19 > s/f19
1057 $ hg add s/f19
1057 $ hg add s/f19
1058 $ hg st -S
1058 $ hg st -S
1059 A s/f19
1059 A s/f19
1060 $ hg forget s/f19
1060 $ hg forget s/f19
1061 $ hg st -S
1061 $ hg st -S
1062 ? s/f19
1062 ? s/f19
1063 $ rm s/f19
1063 $ rm s/f19
1064 $ cd ..
1064 $ cd ..
1065
1065
1066 Courtesy phases synchronisation to publishing server does not block the push
1066 Courtesy phases synchronisation to publishing server does not block the push
1067 (issue3781)
1067 (issue3781)
1068
1068
1069 $ cp -r main issue3781
1069 $ cp -r main issue3781
1070 $ cp -r main issue3781-dest
1070 $ cp -r main issue3781-dest
1071 $ cd issue3781-dest/s
1071 $ cd issue3781-dest/s
1072 $ hg phase tip # show we have draft changeset
1072 $ hg phase tip # show we have draft changeset
1073 5: draft
1073 5: draft
1074 $ chmod a-w .hg/store/phaseroots # prevent phase push
1074 $ chmod a-w .hg/store/phaseroots # prevent phase push
1075 $ cd ../../issue3781
1075 $ cd ../../issue3781
1076 $ cat >> .hg/hgrc << EOF
1076 $ cat >> .hg/hgrc << EOF
1077 > [paths]
1077 > [paths]
1078 > default=../issue3781-dest/
1078 > default=../issue3781-dest/
1079 > EOF
1079 > EOF
1080 $ hg push
1080 $ hg push
1081 pushing to $TESTTMP/issue3781-dest
1081 pushing to $TESTTMP/issue3781-dest
1082 pushing subrepo s to $TESTTMP/issue3781-dest/s
1082 pushing subrepo s to $TESTTMP/issue3781-dest/s
1083 searching for changes
1083 searching for changes
1084 no changes found
1084 no changes found
1085 searching for changes
1085 searching for changes
1086 no changes found
1086 no changes found
1087 [1]
1087 [1]
1088
1088
@@ -1,238 +1,238 b''
1 $ HGMERGE=true; export HGMERGE
1 $ HGMERGE=true; export HGMERGE
2
2
3 $ hg init r1
3 $ hg init r1
4 $ cd r1
4 $ cd r1
5 $ echo a > a
5 $ echo a > a
6 $ hg addremove
6 $ hg addremove
7 adding a
7 adding a
8 $ hg commit -m "1"
8 $ hg commit -m "1"
9
9
10 $ hg clone . ../r2
10 $ hg clone . ../r2
11 updating to branch default
11 updating to branch default
12 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
12 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
13 $ cd ../r2
13 $ cd ../r2
14 $ hg up
14 $ hg up
15 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
15 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
16 $ echo abc > a
16 $ echo abc > a
17 $ hg diff --nodates
17 $ hg diff --nodates
18 diff -r c19d34741b0a a
18 diff -r c19d34741b0a a
19 --- a/a
19 --- a/a
20 +++ b/a
20 +++ b/a
21 @@ -1,1 +1,1 @@
21 @@ -1,1 +1,1 @@
22 -a
22 -a
23 +abc
23 +abc
24
24
25 $ cd ../r1
25 $ cd ../r1
26 $ echo b > b
26 $ echo b > b
27 $ echo a2 > a
27 $ echo a2 > a
28 $ hg addremove
28 $ hg addremove
29 adding b
29 adding b
30 $ hg commit -m "2"
30 $ hg commit -m "2"
31
31
32 $ cd ../r2
32 $ cd ../r2
33 $ hg -q pull ../r1
33 $ hg -q pull ../r1
34 $ hg status
34 $ hg status
35 M a
35 M a
36 $ hg parents
36 $ hg parents
37 changeset: 0:c19d34741b0a
37 changeset: 0:c19d34741b0a
38 user: test
38 user: test
39 date: Thu Jan 01 00:00:00 1970 +0000
39 date: Thu Jan 01 00:00:00 1970 +0000
40 summary: 1
40 summary: 1
41
41
42 $ hg --debug up
42 $ hg --debug up
43 searching for copies back to rev 1
43 searching for copies back to rev 1
44 unmatched files in other:
44 unmatched files in other:
45 b
45 b
46 resolving manifests
46 resolving manifests
47 overwrite: False, partial: False
47 overwrite: False, partial: False
48 ancestor: c19d34741b0a, local: c19d34741b0a+, remote: 1e71731e6fbb
48 ancestor: c19d34741b0a, local: c19d34741b0a+, remote: 1e71731e6fbb
49 a: versions differ -> m
49 a: versions differ -> m
50 preserving a for resolve of a
50 b: remote created -> g
51 b: remote created -> g
51 preserving a for resolve of a
52 updating: a 1/2 files (50.00%)
52 updating: a 1/2 files (50.00%)
53 picked tool 'true' for a (binary False symlink False)
53 picked tool 'true' for a (binary False symlink False)
54 merging a
54 merging a
55 my a@c19d34741b0a+ other a@1e71731e6fbb ancestor a@c19d34741b0a
55 my a@c19d34741b0a+ other a@1e71731e6fbb ancestor a@c19d34741b0a
56 updating: b 2/2 files (100.00%)
56 updating: b 2/2 files (100.00%)
57 getting b
57 getting b
58 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
58 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
59 $ hg parents
59 $ hg parents
60 changeset: 1:1e71731e6fbb
60 changeset: 1:1e71731e6fbb
61 tag: tip
61 tag: tip
62 user: test
62 user: test
63 date: Thu Jan 01 00:00:00 1970 +0000
63 date: Thu Jan 01 00:00:00 1970 +0000
64 summary: 2
64 summary: 2
65
65
66 $ hg --debug up 0
66 $ hg --debug up 0
67 resolving manifests
67 resolving manifests
68 overwrite: False, partial: False
68 overwrite: False, partial: False
69 ancestor: 1e71731e6fbb, local: 1e71731e6fbb+, remote: c19d34741b0a
69 ancestor: 1e71731e6fbb, local: 1e71731e6fbb+, remote: c19d34741b0a
70 b: other deleted -> r
70 a: versions differ -> m
71 a: versions differ -> m
71 b: other deleted -> r
72 preserving a for resolve of a
72 preserving a for resolve of a
73 updating: b 1/2 files (50.00%)
73 updating: b 1/2 files (50.00%)
74 removing b
74 removing b
75 updating: a 2/2 files (100.00%)
75 updating: a 2/2 files (100.00%)
76 picked tool 'true' for a (binary False symlink False)
76 picked tool 'true' for a (binary False symlink False)
77 merging a
77 merging a
78 my a@1e71731e6fbb+ other a@c19d34741b0a ancestor a@1e71731e6fbb
78 my a@1e71731e6fbb+ other a@c19d34741b0a ancestor a@1e71731e6fbb
79 0 files updated, 1 files merged, 1 files removed, 0 files unresolved
79 0 files updated, 1 files merged, 1 files removed, 0 files unresolved
80 $ hg parents
80 $ hg parents
81 changeset: 0:c19d34741b0a
81 changeset: 0:c19d34741b0a
82 user: test
82 user: test
83 date: Thu Jan 01 00:00:00 1970 +0000
83 date: Thu Jan 01 00:00:00 1970 +0000
84 summary: 1
84 summary: 1
85
85
86 $ hg --debug merge
86 $ hg --debug merge
87 abort: nothing to merge
87 abort: nothing to merge
88 (use 'hg update' instead)
88 (use 'hg update' instead)
89 [255]
89 [255]
90 $ hg parents
90 $ hg parents
91 changeset: 0:c19d34741b0a
91 changeset: 0:c19d34741b0a
92 user: test
92 user: test
93 date: Thu Jan 01 00:00:00 1970 +0000
93 date: Thu Jan 01 00:00:00 1970 +0000
94 summary: 1
94 summary: 1
95
95
96 $ hg --debug up
96 $ hg --debug up
97 searching for copies back to rev 1
97 searching for copies back to rev 1
98 unmatched files in other:
98 unmatched files in other:
99 b
99 b
100 resolving manifests
100 resolving manifests
101 overwrite: False, partial: False
101 overwrite: False, partial: False
102 ancestor: c19d34741b0a, local: c19d34741b0a+, remote: 1e71731e6fbb
102 ancestor: c19d34741b0a, local: c19d34741b0a+, remote: 1e71731e6fbb
103 a: versions differ -> m
103 a: versions differ -> m
104 preserving a for resolve of a
104 b: remote created -> g
105 b: remote created -> g
105 preserving a for resolve of a
106 updating: a 1/2 files (50.00%)
106 updating: a 1/2 files (50.00%)
107 picked tool 'true' for a (binary False symlink False)
107 picked tool 'true' for a (binary False symlink False)
108 merging a
108 merging a
109 my a@c19d34741b0a+ other a@1e71731e6fbb ancestor a@c19d34741b0a
109 my a@c19d34741b0a+ other a@1e71731e6fbb ancestor a@c19d34741b0a
110 updating: b 2/2 files (100.00%)
110 updating: b 2/2 files (100.00%)
111 getting b
111 getting b
112 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
112 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
113 $ hg parents
113 $ hg parents
114 changeset: 1:1e71731e6fbb
114 changeset: 1:1e71731e6fbb
115 tag: tip
115 tag: tip
116 user: test
116 user: test
117 date: Thu Jan 01 00:00:00 1970 +0000
117 date: Thu Jan 01 00:00:00 1970 +0000
118 summary: 2
118 summary: 2
119
119
120 $ hg -v history
120 $ hg -v history
121 changeset: 1:1e71731e6fbb
121 changeset: 1:1e71731e6fbb
122 tag: tip
122 tag: tip
123 user: test
123 user: test
124 date: Thu Jan 01 00:00:00 1970 +0000
124 date: Thu Jan 01 00:00:00 1970 +0000
125 files: a b
125 files: a b
126 description:
126 description:
127 2
127 2
128
128
129
129
130 changeset: 0:c19d34741b0a
130 changeset: 0:c19d34741b0a
131 user: test
131 user: test
132 date: Thu Jan 01 00:00:00 1970 +0000
132 date: Thu Jan 01 00:00:00 1970 +0000
133 files: a
133 files: a
134 description:
134 description:
135 1
135 1
136
136
137
137
138 $ hg diff --nodates
138 $ hg diff --nodates
139 diff -r 1e71731e6fbb a
139 diff -r 1e71731e6fbb a
140 --- a/a
140 --- a/a
141 +++ b/a
141 +++ b/a
142 @@ -1,1 +1,1 @@
142 @@ -1,1 +1,1 @@
143 -a2
143 -a2
144 +abc
144 +abc
145
145
146
146
147 create a second head
147 create a second head
148
148
149 $ cd ../r1
149 $ cd ../r1
150 $ hg up 0
150 $ hg up 0
151 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
151 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
152 $ echo b2 > b
152 $ echo b2 > b
153 $ echo a3 > a
153 $ echo a3 > a
154 $ hg addremove
154 $ hg addremove
155 adding b
155 adding b
156 $ hg commit -m "3"
156 $ hg commit -m "3"
157 created new head
157 created new head
158
158
159 $ cd ../r2
159 $ cd ../r2
160 $ hg -q pull ../r1
160 $ hg -q pull ../r1
161 $ hg status
161 $ hg status
162 M a
162 M a
163 $ hg parents
163 $ hg parents
164 changeset: 1:1e71731e6fbb
164 changeset: 1:1e71731e6fbb
165 user: test
165 user: test
166 date: Thu Jan 01 00:00:00 1970 +0000
166 date: Thu Jan 01 00:00:00 1970 +0000
167 summary: 2
167 summary: 2
168
168
169 $ hg --debug up
169 $ hg --debug up
170 abort: crosses branches (merge branches or use --clean to discard changes)
170 abort: crosses branches (merge branches or use --clean to discard changes)
171 [255]
171 [255]
172 $ hg --debug merge
172 $ hg --debug merge
173 abort: outstanding uncommitted changes
173 abort: outstanding uncommitted changes
174 (use 'hg status' to list changes)
174 (use 'hg status' to list changes)
175 [255]
175 [255]
176 $ hg --debug merge -f
176 $ hg --debug merge -f
177 searching for copies back to rev 1
177 searching for copies back to rev 1
178 resolving manifests
178 resolving manifests
179 overwrite: False, partial: False
179 overwrite: False, partial: False
180 ancestor: c19d34741b0a, local: 1e71731e6fbb+, remote: 83c51d0caff4
180 ancestor: c19d34741b0a, local: 1e71731e6fbb+, remote: 83c51d0caff4
181 a: versions differ -> m
181 a: versions differ -> m
182 preserving a for resolve of a
182 b: versions differ -> m
183 b: versions differ -> m
183 preserving a for resolve of a
184 preserving b for resolve of b
184 preserving b for resolve of b
185 updating: a 1/2 files (50.00%)
185 updating: a 1/2 files (50.00%)
186 picked tool 'true' for a (binary False symlink False)
186 picked tool 'true' for a (binary False symlink False)
187 merging a
187 merging a
188 my a@1e71731e6fbb+ other a@83c51d0caff4 ancestor a@c19d34741b0a
188 my a@1e71731e6fbb+ other a@83c51d0caff4 ancestor a@c19d34741b0a
189 updating: b 2/2 files (100.00%)
189 updating: b 2/2 files (100.00%)
190 picked tool 'true' for b (binary False symlink False)
190 picked tool 'true' for b (binary False symlink False)
191 merging b
191 merging b
192 my b@1e71731e6fbb+ other b@83c51d0caff4 ancestor b@000000000000
192 my b@1e71731e6fbb+ other b@83c51d0caff4 ancestor b@000000000000
193 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
193 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
194 (branch merge, don't forget to commit)
194 (branch merge, don't forget to commit)
195 $ hg parents
195 $ hg parents
196 changeset: 1:1e71731e6fbb
196 changeset: 1:1e71731e6fbb
197 user: test
197 user: test
198 date: Thu Jan 01 00:00:00 1970 +0000
198 date: Thu Jan 01 00:00:00 1970 +0000
199 summary: 2
199 summary: 2
200
200
201 changeset: 2:83c51d0caff4
201 changeset: 2:83c51d0caff4
202 tag: tip
202 tag: tip
203 parent: 0:c19d34741b0a
203 parent: 0:c19d34741b0a
204 user: test
204 user: test
205 date: Thu Jan 01 00:00:00 1970 +0000
205 date: Thu Jan 01 00:00:00 1970 +0000
206 summary: 3
206 summary: 3
207
207
208 $ hg diff --nodates
208 $ hg diff --nodates
209 diff -r 1e71731e6fbb a
209 diff -r 1e71731e6fbb a
210 --- a/a
210 --- a/a
211 +++ b/a
211 +++ b/a
212 @@ -1,1 +1,1 @@
212 @@ -1,1 +1,1 @@
213 -a2
213 -a2
214 +abc
214 +abc
215
215
216
216
217 test a local add
217 test a local add
218
218
219 $ cd ..
219 $ cd ..
220 $ hg init a
220 $ hg init a
221 $ hg init b
221 $ hg init b
222 $ echo a > a/a
222 $ echo a > a/a
223 $ echo a > b/a
223 $ echo a > b/a
224 $ hg --cwd a commit -A -m a
224 $ hg --cwd a commit -A -m a
225 adding a
225 adding a
226 $ cd b
226 $ cd b
227 $ hg add a
227 $ hg add a
228 $ hg pull -u ../a
228 $ hg pull -u ../a
229 pulling from ../a
229 pulling from ../a
230 requesting all changes
230 requesting all changes
231 adding changesets
231 adding changesets
232 adding manifests
232 adding manifests
233 adding file changes
233 adding file changes
234 added 1 changesets with 1 changes to 1 files
234 added 1 changesets with 1 changes to 1 files
235 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
235 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
236 $ hg st
236 $ hg st
237
237
238 $ cd ..
238 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now