##// END OF EJS Templates
largefiles: don't interfere with logging normal files...
Matt Harbison -
r23976:34493912 stable
parent child Browse files
Show More
@@ -1,1341 +1,1346 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, util, cmdutil, scmutil, match as match_, \
14 from mercurial import hg, util, cmdutil, scmutil, match as match_, \
15 archival, pathutil, revset
15 archival, pathutil, revset
16 from mercurial.i18n import _
16 from mercurial.i18n import _
17 from mercurial.node import hex
17 from mercurial.node import hex
18
18
19 import lfutil
19 import lfutil
20 import lfcommands
20 import lfcommands
21 import basestore
21 import basestore
22
22
23 # -- Utility functions: commonly/repeatedly needed functionality ---------------
23 # -- Utility functions: commonly/repeatedly needed functionality ---------------
24
24
25 def composelargefilematcher(match, manifest):
25 def composelargefilematcher(match, manifest):
26 '''create a matcher that matches only the largefiles in the original
26 '''create a matcher that matches only the largefiles in the original
27 matcher'''
27 matcher'''
28 m = copy.copy(match)
28 m = copy.copy(match)
29 lfile = lambda f: lfutil.standin(f) in manifest
29 lfile = lambda f: lfutil.standin(f) in manifest
30 m._files = filter(lfile, m._files)
30 m._files = filter(lfile, m._files)
31 m._fmap = set(m._files)
31 m._fmap = set(m._files)
32 m._always = False
32 m._always = False
33 origmatchfn = m.matchfn
33 origmatchfn = m.matchfn
34 m.matchfn = lambda f: lfile(f) and origmatchfn(f)
34 m.matchfn = lambda f: lfile(f) and origmatchfn(f)
35 return m
35 return m
36
36
37 def composenormalfilematcher(match, manifest, exclude=None):
37 def composenormalfilematcher(match, manifest, exclude=None):
38 excluded = set()
38 excluded = set()
39 if exclude is not None:
39 if exclude is not None:
40 excluded.update(exclude)
40 excluded.update(exclude)
41
41
42 m = copy.copy(match)
42 m = copy.copy(match)
43 notlfile = lambda f: not (lfutil.isstandin(f) or lfutil.standin(f) in
43 notlfile = lambda f: not (lfutil.isstandin(f) or lfutil.standin(f) in
44 manifest or f in excluded)
44 manifest or f in excluded)
45 m._files = filter(notlfile, m._files)
45 m._files = filter(notlfile, m._files)
46 m._fmap = set(m._files)
46 m._fmap = set(m._files)
47 m._always = False
47 m._always = False
48 origmatchfn = m.matchfn
48 origmatchfn = m.matchfn
49 m.matchfn = lambda f: notlfile(f) and origmatchfn(f)
49 m.matchfn = lambda f: notlfile(f) and origmatchfn(f)
50 return m
50 return m
51
51
52 def installnormalfilesmatchfn(manifest):
52 def installnormalfilesmatchfn(manifest):
53 '''installmatchfn with a matchfn that ignores all largefiles'''
53 '''installmatchfn with a matchfn that ignores all largefiles'''
54 def overridematch(ctx, pats=[], opts={}, globbed=False,
54 def overridematch(ctx, pats=[], opts={}, globbed=False,
55 default='relpath'):
55 default='relpath'):
56 match = oldmatch(ctx, pats, opts, globbed, default)
56 match = oldmatch(ctx, pats, opts, globbed, default)
57 return composenormalfilematcher(match, manifest)
57 return composenormalfilematcher(match, manifest)
58 oldmatch = installmatchfn(overridematch)
58 oldmatch = installmatchfn(overridematch)
59
59
60 def installmatchfn(f):
60 def installmatchfn(f):
61 '''monkey patch the scmutil module with a custom match function.
61 '''monkey patch the scmutil module with a custom match function.
62 Warning: it is monkey patching the _module_ on runtime! Not thread safe!'''
62 Warning: it is monkey patching the _module_ on runtime! Not thread safe!'''
63 oldmatch = scmutil.match
63 oldmatch = scmutil.match
64 setattr(f, 'oldmatch', oldmatch)
64 setattr(f, 'oldmatch', oldmatch)
65 scmutil.match = f
65 scmutil.match = f
66 return oldmatch
66 return oldmatch
67
67
68 def restorematchfn():
68 def restorematchfn():
69 '''restores scmutil.match to what it was before installmatchfn
69 '''restores scmutil.match to what it was before installmatchfn
70 was called. no-op if scmutil.match is its original function.
70 was called. no-op if scmutil.match is its original function.
71
71
72 Note that n calls to installmatchfn will require n calls to
72 Note that n calls to installmatchfn will require n calls to
73 restore the original matchfn.'''
73 restore the original matchfn.'''
74 scmutil.match = getattr(scmutil.match, 'oldmatch')
74 scmutil.match = getattr(scmutil.match, 'oldmatch')
75
75
76 def installmatchandpatsfn(f):
76 def installmatchandpatsfn(f):
77 oldmatchandpats = scmutil.matchandpats
77 oldmatchandpats = scmutil.matchandpats
78 setattr(f, 'oldmatchandpats', oldmatchandpats)
78 setattr(f, 'oldmatchandpats', oldmatchandpats)
79 scmutil.matchandpats = f
79 scmutil.matchandpats = f
80 return oldmatchandpats
80 return oldmatchandpats
81
81
82 def restorematchandpatsfn():
82 def restorematchandpatsfn():
83 '''restores scmutil.matchandpats to what it was before
83 '''restores scmutil.matchandpats to what it was before
84 installmatchandpatsfn was called. No-op if scmutil.matchandpats
84 installmatchandpatsfn was called. No-op if scmutil.matchandpats
85 is its original function.
85 is its original function.
86
86
87 Note that n calls to installmatchandpatsfn will require n calls
87 Note that n calls to installmatchandpatsfn will require n calls
88 to restore the original matchfn.'''
88 to restore the original matchfn.'''
89 scmutil.matchandpats = getattr(scmutil.matchandpats, 'oldmatchandpats',
89 scmutil.matchandpats = getattr(scmutil.matchandpats, 'oldmatchandpats',
90 scmutil.matchandpats)
90 scmutil.matchandpats)
91
91
92 def addlargefiles(ui, repo, isaddremove, matcher, **opts):
92 def addlargefiles(ui, repo, isaddremove, matcher, **opts):
93 large = opts.get('large')
93 large = opts.get('large')
94 lfsize = lfutil.getminsize(
94 lfsize = lfutil.getminsize(
95 ui, lfutil.islfilesrepo(repo), opts.get('lfsize'))
95 ui, lfutil.islfilesrepo(repo), opts.get('lfsize'))
96
96
97 lfmatcher = None
97 lfmatcher = None
98 if lfutil.islfilesrepo(repo):
98 if lfutil.islfilesrepo(repo):
99 lfpats = ui.configlist(lfutil.longname, 'patterns', default=[])
99 lfpats = ui.configlist(lfutil.longname, 'patterns', default=[])
100 if lfpats:
100 if lfpats:
101 lfmatcher = match_.match(repo.root, '', list(lfpats))
101 lfmatcher = match_.match(repo.root, '', list(lfpats))
102
102
103 lfnames = []
103 lfnames = []
104 m = copy.copy(matcher)
104 m = copy.copy(matcher)
105 m.bad = lambda x, y: None
105 m.bad = lambda x, y: None
106 wctx = repo[None]
106 wctx = repo[None]
107 for f in repo.walk(m):
107 for f in repo.walk(m):
108 exact = m.exact(f)
108 exact = m.exact(f)
109 lfile = lfutil.standin(f) in wctx
109 lfile = lfutil.standin(f) in wctx
110 nfile = f in wctx
110 nfile = f in wctx
111 exists = lfile or nfile
111 exists = lfile or nfile
112
112
113 # addremove in core gets fancy with the name, add doesn't
113 # addremove in core gets fancy with the name, add doesn't
114 if isaddremove:
114 if isaddremove:
115 name = m.uipath(f)
115 name = m.uipath(f)
116 else:
116 else:
117 name = m.rel(f)
117 name = m.rel(f)
118
118
119 # Don't warn the user when they attempt to add a normal tracked file.
119 # Don't warn the user when they attempt to add a normal tracked file.
120 # The normal add code will do that for us.
120 # The normal add code will do that for us.
121 if exact and exists:
121 if exact and exists:
122 if lfile:
122 if lfile:
123 ui.warn(_('%s already a largefile\n') % name)
123 ui.warn(_('%s already a largefile\n') % name)
124 continue
124 continue
125
125
126 if (exact or not exists) and not lfutil.isstandin(f):
126 if (exact or not exists) and not lfutil.isstandin(f):
127 # In case the file was removed previously, but not committed
127 # In case the file was removed previously, but not committed
128 # (issue3507)
128 # (issue3507)
129 if not repo.wvfs.exists(f):
129 if not repo.wvfs.exists(f):
130 continue
130 continue
131
131
132 abovemin = (lfsize and
132 abovemin = (lfsize and
133 repo.wvfs.lstat(f).st_size >= lfsize * 1024 * 1024)
133 repo.wvfs.lstat(f).st_size >= lfsize * 1024 * 1024)
134 if large or abovemin or (lfmatcher and lfmatcher(f)):
134 if large or abovemin or (lfmatcher and lfmatcher(f)):
135 lfnames.append(f)
135 lfnames.append(f)
136 if ui.verbose or not exact:
136 if ui.verbose or not exact:
137 ui.status(_('adding %s as a largefile\n') % name)
137 ui.status(_('adding %s as a largefile\n') % name)
138
138
139 bad = []
139 bad = []
140
140
141 # Need to lock, otherwise there could be a race condition between
141 # Need to lock, otherwise there could be a race condition between
142 # when standins are created and added to the repo.
142 # when standins are created and added to the repo.
143 wlock = repo.wlock()
143 wlock = repo.wlock()
144 try:
144 try:
145 if not opts.get('dry_run'):
145 if not opts.get('dry_run'):
146 standins = []
146 standins = []
147 lfdirstate = lfutil.openlfdirstate(ui, repo)
147 lfdirstate = lfutil.openlfdirstate(ui, repo)
148 for f in lfnames:
148 for f in lfnames:
149 standinname = lfutil.standin(f)
149 standinname = lfutil.standin(f)
150 lfutil.writestandin(repo, standinname, hash='',
150 lfutil.writestandin(repo, standinname, hash='',
151 executable=lfutil.getexecutable(repo.wjoin(f)))
151 executable=lfutil.getexecutable(repo.wjoin(f)))
152 standins.append(standinname)
152 standins.append(standinname)
153 if lfdirstate[f] == 'r':
153 if lfdirstate[f] == 'r':
154 lfdirstate.normallookup(f)
154 lfdirstate.normallookup(f)
155 else:
155 else:
156 lfdirstate.add(f)
156 lfdirstate.add(f)
157 lfdirstate.write()
157 lfdirstate.write()
158 bad += [lfutil.splitstandin(f)
158 bad += [lfutil.splitstandin(f)
159 for f in repo[None].add(standins)
159 for f in repo[None].add(standins)
160 if f in m.files()]
160 if f in m.files()]
161
161
162 added = [f for f in lfnames if f not in bad]
162 added = [f for f in lfnames if f not in bad]
163 finally:
163 finally:
164 wlock.release()
164 wlock.release()
165 return added, bad
165 return added, bad
166
166
167 def removelargefiles(ui, repo, isaddremove, matcher, **opts):
167 def removelargefiles(ui, repo, isaddremove, matcher, **opts):
168 after = opts.get('after')
168 after = opts.get('after')
169 m = composelargefilematcher(matcher, repo[None].manifest())
169 m = composelargefilematcher(matcher, repo[None].manifest())
170 try:
170 try:
171 repo.lfstatus = True
171 repo.lfstatus = True
172 s = repo.status(match=m, clean=not isaddremove)
172 s = repo.status(match=m, clean=not isaddremove)
173 finally:
173 finally:
174 repo.lfstatus = False
174 repo.lfstatus = False
175 manifest = repo[None].manifest()
175 manifest = repo[None].manifest()
176 modified, added, deleted, clean = [[f for f in list
176 modified, added, deleted, clean = [[f for f in list
177 if lfutil.standin(f) in manifest]
177 if lfutil.standin(f) in manifest]
178 for list in (s.modified, s.added,
178 for list in (s.modified, s.added,
179 s.deleted, s.clean)]
179 s.deleted, s.clean)]
180
180
181 def warn(files, msg):
181 def warn(files, msg):
182 for f in files:
182 for f in files:
183 ui.warn(msg % m.rel(f))
183 ui.warn(msg % m.rel(f))
184 return int(len(files) > 0)
184 return int(len(files) > 0)
185
185
186 result = 0
186 result = 0
187
187
188 if after:
188 if after:
189 remove = deleted
189 remove = deleted
190 result = warn(modified + added + clean,
190 result = warn(modified + added + clean,
191 _('not removing %s: file still exists\n'))
191 _('not removing %s: file still exists\n'))
192 else:
192 else:
193 remove = deleted + clean
193 remove = deleted + clean
194 result = warn(modified, _('not removing %s: file is modified (use -f'
194 result = warn(modified, _('not removing %s: file is modified (use -f'
195 ' to force removal)\n'))
195 ' to force removal)\n'))
196 result = warn(added, _('not removing %s: file has been marked for add'
196 result = warn(added, _('not removing %s: file has been marked for add'
197 ' (use forget to undo)\n')) or result
197 ' (use forget to undo)\n')) or result
198
198
199 # Need to lock because standin files are deleted then removed from the
199 # Need to lock because standin files are deleted then removed from the
200 # repository and we could race in-between.
200 # repository and we could race in-between.
201 wlock = repo.wlock()
201 wlock = repo.wlock()
202 try:
202 try:
203 lfdirstate = lfutil.openlfdirstate(ui, repo)
203 lfdirstate = lfutil.openlfdirstate(ui, repo)
204 for f in sorted(remove):
204 for f in sorted(remove):
205 if ui.verbose or not m.exact(f):
205 if ui.verbose or not m.exact(f):
206 # addremove in core gets fancy with the name, remove doesn't
206 # addremove in core gets fancy with the name, remove doesn't
207 if isaddremove:
207 if isaddremove:
208 name = m.uipath(f)
208 name = m.uipath(f)
209 else:
209 else:
210 name = m.rel(f)
210 name = m.rel(f)
211 ui.status(_('removing %s\n') % name)
211 ui.status(_('removing %s\n') % name)
212
212
213 if not opts.get('dry_run'):
213 if not opts.get('dry_run'):
214 if not after:
214 if not after:
215 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
215 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
216
216
217 if opts.get('dry_run'):
217 if opts.get('dry_run'):
218 return result
218 return result
219
219
220 remove = [lfutil.standin(f) for f in remove]
220 remove = [lfutil.standin(f) for f in remove]
221 # If this is being called by addremove, let the original addremove
221 # If this is being called by addremove, let the original addremove
222 # function handle this.
222 # function handle this.
223 if not isaddremove:
223 if not isaddremove:
224 for f in remove:
224 for f in remove:
225 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
225 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
226 repo[None].forget(remove)
226 repo[None].forget(remove)
227
227
228 for f in remove:
228 for f in remove:
229 lfutil.synclfdirstate(repo, lfdirstate, lfutil.splitstandin(f),
229 lfutil.synclfdirstate(repo, lfdirstate, lfutil.splitstandin(f),
230 False)
230 False)
231
231
232 lfdirstate.write()
232 lfdirstate.write()
233 finally:
233 finally:
234 wlock.release()
234 wlock.release()
235
235
236 return result
236 return result
237
237
238 # For overriding mercurial.hgweb.webcommands so that largefiles will
238 # For overriding mercurial.hgweb.webcommands so that largefiles will
239 # appear at their right place in the manifests.
239 # appear at their right place in the manifests.
240 def decodepath(orig, path):
240 def decodepath(orig, path):
241 return lfutil.splitstandin(path) or path
241 return lfutil.splitstandin(path) or path
242
242
243 # -- Wrappers: modify existing commands --------------------------------
243 # -- Wrappers: modify existing commands --------------------------------
244
244
245 def overrideadd(orig, ui, repo, *pats, **opts):
245 def overrideadd(orig, ui, repo, *pats, **opts):
246 if opts.get('normal') and opts.get('large'):
246 if opts.get('normal') and opts.get('large'):
247 raise util.Abort(_('--normal cannot be used with --large'))
247 raise util.Abort(_('--normal cannot be used with --large'))
248 return orig(ui, repo, *pats, **opts)
248 return orig(ui, repo, *pats, **opts)
249
249
250 def cmdutiladd(orig, ui, repo, matcher, prefix, explicitonly, **opts):
250 def cmdutiladd(orig, ui, repo, matcher, prefix, explicitonly, **opts):
251 # The --normal flag short circuits this override
251 # The --normal flag short circuits this override
252 if opts.get('normal'):
252 if opts.get('normal'):
253 return orig(ui, repo, matcher, prefix, explicitonly, **opts)
253 return orig(ui, repo, matcher, prefix, explicitonly, **opts)
254
254
255 ladded, lbad = addlargefiles(ui, repo, False, matcher, **opts)
255 ladded, lbad = addlargefiles(ui, repo, False, matcher, **opts)
256 normalmatcher = composenormalfilematcher(matcher, repo[None].manifest(),
256 normalmatcher = composenormalfilematcher(matcher, repo[None].manifest(),
257 ladded)
257 ladded)
258 bad = orig(ui, repo, normalmatcher, prefix, explicitonly, **opts)
258 bad = orig(ui, repo, normalmatcher, prefix, explicitonly, **opts)
259
259
260 bad.extend(f for f in lbad)
260 bad.extend(f for f in lbad)
261 return bad
261 return bad
262
262
263 def cmdutilremove(orig, ui, repo, matcher, prefix, after, force, subrepos):
263 def cmdutilremove(orig, ui, repo, matcher, prefix, after, force, subrepos):
264 normalmatcher = composenormalfilematcher(matcher, repo[None].manifest())
264 normalmatcher = composenormalfilematcher(matcher, repo[None].manifest())
265 result = orig(ui, repo, normalmatcher, prefix, after, force, subrepos)
265 result = orig(ui, repo, normalmatcher, prefix, after, force, subrepos)
266 return removelargefiles(ui, repo, False, matcher, after=after,
266 return removelargefiles(ui, repo, False, matcher, after=after,
267 force=force) or result
267 force=force) or result
268
268
269 def overridestatusfn(orig, repo, rev2, **opts):
269 def overridestatusfn(orig, repo, rev2, **opts):
270 try:
270 try:
271 repo._repo.lfstatus = True
271 repo._repo.lfstatus = True
272 return orig(repo, rev2, **opts)
272 return orig(repo, rev2, **opts)
273 finally:
273 finally:
274 repo._repo.lfstatus = False
274 repo._repo.lfstatus = False
275
275
276 def overridestatus(orig, ui, repo, *pats, **opts):
276 def overridestatus(orig, ui, repo, *pats, **opts):
277 try:
277 try:
278 repo.lfstatus = True
278 repo.lfstatus = True
279 return orig(ui, repo, *pats, **opts)
279 return orig(ui, repo, *pats, **opts)
280 finally:
280 finally:
281 repo.lfstatus = False
281 repo.lfstatus = False
282
282
283 def overridedirty(orig, repo, ignoreupdate=False):
283 def overridedirty(orig, repo, ignoreupdate=False):
284 try:
284 try:
285 repo._repo.lfstatus = True
285 repo._repo.lfstatus = True
286 return orig(repo, ignoreupdate)
286 return orig(repo, ignoreupdate)
287 finally:
287 finally:
288 repo._repo.lfstatus = False
288 repo._repo.lfstatus = False
289
289
290 def overridelog(orig, ui, repo, *pats, **opts):
290 def overridelog(orig, ui, repo, *pats, **opts):
291 def overridematchandpats(ctx, pats=[], opts={}, globbed=False,
291 def overridematchandpats(ctx, pats=[], opts={}, globbed=False,
292 default='relpath'):
292 default='relpath'):
293 """Matcher that merges root directory with .hglf, suitable for log.
293 """Matcher that merges root directory with .hglf, suitable for log.
294 It is still possible to match .hglf directly.
294 It is still possible to match .hglf directly.
295 For any listed files run log on the standin too.
295 For any listed files run log on the standin too.
296 matchfn tries both the given filename and with .hglf stripped.
296 matchfn tries both the given filename and with .hglf stripped.
297 """
297 """
298 matchandpats = oldmatchandpats(ctx, pats, opts, globbed, default)
298 matchandpats = oldmatchandpats(ctx, pats, opts, globbed, default)
299 m, p = copy.copy(matchandpats)
299 m, p = copy.copy(matchandpats)
300
300
301 if m.always():
301 if m.always():
302 # We want to match everything anyway, so there's no benefit trying
302 # We want to match everything anyway, so there's no benefit trying
303 # to add standins.
303 # to add standins.
304 return matchandpats
304 return matchandpats
305
305
306 pats = set(p)
306 pats = set(p)
307 # TODO: handling of patterns in both cases below
307 # TODO: handling of patterns in both cases below
308 if m._cwd:
308 if m._cwd:
309 if os.path.isabs(m._cwd):
309 if os.path.isabs(m._cwd):
310 # TODO: handle largefile magic when invoked from other cwd
310 # TODO: handle largefile magic when invoked from other cwd
311 return matchandpats
311 return matchandpats
312 back = (m._cwd.count('/') + 1) * '../'
312 back = (m._cwd.count('/') + 1) * '../'
313 pats.update(back + lfutil.standin(m._cwd + '/' + f) for f in p)
313 pats.update(back + lfutil.standin(m._cwd + '/' + f) for f in p)
314 else:
314 else:
315 pats.update(lfutil.standin(f) for f in p)
315 pats.update(lfutil.standin(f) for f in p)
316
316
317 for i in range(0, len(m._files)):
317 for i in range(0, len(m._files)):
318 standin = lfutil.standin(m._files[i])
318 standin = lfutil.standin(m._files[i])
319 # If the "standin" is a directory, append instead of replace to
320 # support naming a directory on the command line with only
321 # largefiles. The original directory is kept to support normal
322 # files.
319 if standin in repo[ctx.node()]:
323 if standin in repo[ctx.node()]:
320 m._files[i] = standin
324 m._files[i] = standin
321 elif m._files[i] not in repo[ctx.node()]:
325 elif m._files[i] not in repo[ctx.node()] \
326 and repo.wvfs.isdir(standin):
322 m._files.append(standin)
327 m._files.append(standin)
323 pats.add(standin)
328 pats.add(standin)
324
329
325 m._fmap = set(m._files)
330 m._fmap = set(m._files)
326 m._always = False
331 m._always = False
327 origmatchfn = m.matchfn
332 origmatchfn = m.matchfn
328 def lfmatchfn(f):
333 def lfmatchfn(f):
329 lf = lfutil.splitstandin(f)
334 lf = lfutil.splitstandin(f)
330 if lf is not None and origmatchfn(lf):
335 if lf is not None and origmatchfn(lf):
331 return True
336 return True
332 r = origmatchfn(f)
337 r = origmatchfn(f)
333 return r
338 return r
334 m.matchfn = lfmatchfn
339 m.matchfn = lfmatchfn
335
340
336 return m, pats
341 return m, pats
337
342
338 # For hg log --patch, the match object is used in two different senses:
343 # For hg log --patch, the match object is used in two different senses:
339 # (1) to determine what revisions should be printed out, and
344 # (1) to determine what revisions should be printed out, and
340 # (2) to determine what files to print out diffs for.
345 # (2) to determine what files to print out diffs for.
341 # The magic matchandpats override should be used for case (1) but not for
346 # The magic matchandpats override should be used for case (1) but not for
342 # case (2).
347 # case (2).
343 def overridemakelogfilematcher(repo, pats, opts):
348 def overridemakelogfilematcher(repo, pats, opts):
344 pctx = repo[None]
349 pctx = repo[None]
345 match, pats = oldmatchandpats(pctx, pats, opts)
350 match, pats = oldmatchandpats(pctx, pats, opts)
346 return lambda rev: match
351 return lambda rev: match
347
352
348 oldmatchandpats = installmatchandpatsfn(overridematchandpats)
353 oldmatchandpats = installmatchandpatsfn(overridematchandpats)
349 oldmakelogfilematcher = cmdutil._makenofollowlogfilematcher
354 oldmakelogfilematcher = cmdutil._makenofollowlogfilematcher
350 setattr(cmdutil, '_makenofollowlogfilematcher', overridemakelogfilematcher)
355 setattr(cmdutil, '_makenofollowlogfilematcher', overridemakelogfilematcher)
351
356
352 try:
357 try:
353 return orig(ui, repo, *pats, **opts)
358 return orig(ui, repo, *pats, **opts)
354 finally:
359 finally:
355 restorematchandpatsfn()
360 restorematchandpatsfn()
356 setattr(cmdutil, '_makenofollowlogfilematcher', oldmakelogfilematcher)
361 setattr(cmdutil, '_makenofollowlogfilematcher', oldmakelogfilematcher)
357
362
358 def overrideverify(orig, ui, repo, *pats, **opts):
363 def overrideverify(orig, ui, repo, *pats, **opts):
359 large = opts.pop('large', False)
364 large = opts.pop('large', False)
360 all = opts.pop('lfa', False)
365 all = opts.pop('lfa', False)
361 contents = opts.pop('lfc', False)
366 contents = opts.pop('lfc', False)
362
367
363 result = orig(ui, repo, *pats, **opts)
368 result = orig(ui, repo, *pats, **opts)
364 if large or all or contents:
369 if large or all or contents:
365 result = result or lfcommands.verifylfiles(ui, repo, all, contents)
370 result = result or lfcommands.verifylfiles(ui, repo, all, contents)
366 return result
371 return result
367
372
368 def overridedebugstate(orig, ui, repo, *pats, **opts):
373 def overridedebugstate(orig, ui, repo, *pats, **opts):
369 large = opts.pop('large', False)
374 large = opts.pop('large', False)
370 if large:
375 if large:
371 class fakerepo(object):
376 class fakerepo(object):
372 dirstate = lfutil.openlfdirstate(ui, repo)
377 dirstate = lfutil.openlfdirstate(ui, repo)
373 orig(ui, fakerepo, *pats, **opts)
378 orig(ui, fakerepo, *pats, **opts)
374 else:
379 else:
375 orig(ui, repo, *pats, **opts)
380 orig(ui, repo, *pats, **opts)
376
381
377 # Override needs to refresh standins so that update's normal merge
382 # Override needs to refresh standins so that update's normal merge
378 # will go through properly. Then the other update hook (overriding repo.update)
383 # will go through properly. Then the other update hook (overriding repo.update)
379 # will get the new files. Filemerge is also overridden so that the merge
384 # will get the new files. Filemerge is also overridden so that the merge
380 # will merge standins correctly.
385 # will merge standins correctly.
381 def overrideupdate(orig, ui, repo, *pats, **opts):
386 def overrideupdate(orig, ui, repo, *pats, **opts):
382 # Need to lock between the standins getting updated and their
387 # Need to lock between the standins getting updated and their
383 # largefiles getting updated
388 # largefiles getting updated
384 wlock = repo.wlock()
389 wlock = repo.wlock()
385 try:
390 try:
386 if opts['check']:
391 if opts['check']:
387 lfdirstate = lfutil.openlfdirstate(ui, repo)
392 lfdirstate = lfutil.openlfdirstate(ui, repo)
388 unsure, s = lfdirstate.status(
393 unsure, s = lfdirstate.status(
389 match_.always(repo.root, repo.getcwd()),
394 match_.always(repo.root, repo.getcwd()),
390 [], False, False, False)
395 [], False, False, False)
391
396
392 mod = len(s.modified) > 0
397 mod = len(s.modified) > 0
393 for lfile in unsure:
398 for lfile in unsure:
394 standin = lfutil.standin(lfile)
399 standin = lfutil.standin(lfile)
395 if repo['.'][standin].data().strip() != \
400 if repo['.'][standin].data().strip() != \
396 lfutil.hashfile(repo.wjoin(lfile)):
401 lfutil.hashfile(repo.wjoin(lfile)):
397 mod = True
402 mod = True
398 else:
403 else:
399 lfdirstate.normal(lfile)
404 lfdirstate.normal(lfile)
400 lfdirstate.write()
405 lfdirstate.write()
401 if mod:
406 if mod:
402 raise util.Abort(_('uncommitted changes'))
407 raise util.Abort(_('uncommitted changes'))
403 return orig(ui, repo, *pats, **opts)
408 return orig(ui, repo, *pats, **opts)
404 finally:
409 finally:
405 wlock.release()
410 wlock.release()
406
411
407 # Before starting the manifest merge, merge.updates will call
412 # Before starting the manifest merge, merge.updates will call
408 # _checkunknownfile to check if there are any files in the merged-in
413 # _checkunknownfile to check if there are any files in the merged-in
409 # changeset that collide with unknown files in the working copy.
414 # changeset that collide with unknown files in the working copy.
410 #
415 #
411 # The largefiles are seen as unknown, so this prevents us from merging
416 # The largefiles are seen as unknown, so this prevents us from merging
412 # in a file 'foo' if we already have a largefile with the same name.
417 # in a file 'foo' if we already have a largefile with the same name.
413 #
418 #
414 # The overridden function filters the unknown files by removing any
419 # The overridden function filters the unknown files by removing any
415 # largefiles. This makes the merge proceed and we can then handle this
420 # largefiles. This makes the merge proceed and we can then handle this
416 # case further in the overridden calculateupdates function below.
421 # case further in the overridden calculateupdates function below.
417 def overridecheckunknownfile(origfn, repo, wctx, mctx, f, f2=None):
422 def overridecheckunknownfile(origfn, repo, wctx, mctx, f, f2=None):
418 if lfutil.standin(repo.dirstate.normalize(f)) in wctx:
423 if lfutil.standin(repo.dirstate.normalize(f)) in wctx:
419 return False
424 return False
420 return origfn(repo, wctx, mctx, f, f2)
425 return origfn(repo, wctx, mctx, f, f2)
421
426
422 # The manifest merge handles conflicts on the manifest level. We want
427 # The manifest merge handles conflicts on the manifest level. We want
423 # to handle changes in largefile-ness of files at this level too.
428 # to handle changes in largefile-ness of files at this level too.
424 #
429 #
425 # The strategy is to run the original calculateupdates and then process
430 # The strategy is to run the original calculateupdates and then process
426 # the action list it outputs. There are two cases we need to deal with:
431 # the action list it outputs. There are two cases we need to deal with:
427 #
432 #
428 # 1. Normal file in p1, largefile in p2. Here the largefile is
433 # 1. Normal file in p1, largefile in p2. Here the largefile is
429 # detected via its standin file, which will enter the working copy
434 # detected via its standin file, which will enter the working copy
430 # with a "get" action. It is not "merge" since the standin is all
435 # with a "get" action. It is not "merge" since the standin is all
431 # Mercurial is concerned with at this level -- the link to the
436 # Mercurial is concerned with at this level -- the link to the
432 # existing normal file is not relevant here.
437 # existing normal file is not relevant here.
433 #
438 #
434 # 2. Largefile in p1, normal file in p2. Here we get a "merge" action
439 # 2. Largefile in p1, normal file in p2. Here we get a "merge" action
435 # since the largefile will be present in the working copy and
440 # since the largefile will be present in the working copy and
436 # different from the normal file in p2. Mercurial therefore
441 # different from the normal file in p2. Mercurial therefore
437 # triggers a merge action.
442 # triggers a merge action.
438 #
443 #
439 # In both cases, we prompt the user and emit new actions to either
444 # In both cases, we prompt the user and emit new actions to either
440 # remove the standin (if the normal file was kept) or to remove the
445 # remove the standin (if the normal file was kept) or to remove the
441 # normal file and get the standin (if the largefile was kept). The
446 # normal file and get the standin (if the largefile was kept). The
442 # default prompt answer is to use the largefile version since it was
447 # default prompt answer is to use the largefile version since it was
443 # presumably changed on purpose.
448 # presumably changed on purpose.
444 #
449 #
445 # Finally, the merge.applyupdates function will then take care of
450 # Finally, the merge.applyupdates function will then take care of
446 # writing the files into the working copy and lfcommands.updatelfiles
451 # writing the files into the working copy and lfcommands.updatelfiles
447 # will update the largefiles.
452 # will update the largefiles.
448 def overridecalculateupdates(origfn, repo, p1, p2, pas, branchmerge, force,
453 def overridecalculateupdates(origfn, repo, p1, p2, pas, branchmerge, force,
449 partial, acceptremote, followcopies):
454 partial, acceptremote, followcopies):
450 overwrite = force and not branchmerge
455 overwrite = force and not branchmerge
451 actions, diverge, renamedelete = origfn(
456 actions, diverge, renamedelete = origfn(
452 repo, p1, p2, pas, branchmerge, force, partial, acceptremote,
457 repo, p1, p2, pas, branchmerge, force, partial, acceptremote,
453 followcopies)
458 followcopies)
454
459
455 if overwrite:
460 if overwrite:
456 return actions, diverge, renamedelete
461 return actions, diverge, renamedelete
457
462
458 # Convert to dictionary with filename as key and action as value.
463 # Convert to dictionary with filename as key and action as value.
459 lfiles = set()
464 lfiles = set()
460 for f in actions:
465 for f in actions:
461 splitstandin = f and lfutil.splitstandin(f)
466 splitstandin = f and lfutil.splitstandin(f)
462 if splitstandin in p1:
467 if splitstandin in p1:
463 lfiles.add(splitstandin)
468 lfiles.add(splitstandin)
464 elif lfutil.standin(f) in p1:
469 elif lfutil.standin(f) in p1:
465 lfiles.add(f)
470 lfiles.add(f)
466
471
467 for lfile in lfiles:
472 for lfile in lfiles:
468 standin = lfutil.standin(lfile)
473 standin = lfutil.standin(lfile)
469 (lm, largs, lmsg) = actions.get(lfile, (None, None, None))
474 (lm, largs, lmsg) = actions.get(lfile, (None, None, None))
470 (sm, sargs, smsg) = actions.get(standin, (None, None, None))
475 (sm, sargs, smsg) = actions.get(standin, (None, None, None))
471 if sm in ('g', 'dc') and lm != 'r':
476 if sm in ('g', 'dc') and lm != 'r':
472 # Case 1: normal file in the working copy, largefile in
477 # Case 1: normal file in the working copy, largefile in
473 # the second parent
478 # the second parent
474 usermsg = _('remote turned local normal file %s into a largefile\n'
479 usermsg = _('remote turned local normal file %s into a largefile\n'
475 'use (l)argefile or keep (n)ormal file?'
480 'use (l)argefile or keep (n)ormal file?'
476 '$$ &Largefile $$ &Normal file') % lfile
481 '$$ &Largefile $$ &Normal file') % lfile
477 if repo.ui.promptchoice(usermsg, 0) == 0: # pick remote largefile
482 if repo.ui.promptchoice(usermsg, 0) == 0: # pick remote largefile
478 actions[lfile] = ('r', None, 'replaced by standin')
483 actions[lfile] = ('r', None, 'replaced by standin')
479 actions[standin] = ('g', sargs, 'replaces standin')
484 actions[standin] = ('g', sargs, 'replaces standin')
480 else: # keep local normal file
485 else: # keep local normal file
481 actions[lfile] = ('k', None, 'replaces standin')
486 actions[lfile] = ('k', None, 'replaces standin')
482 if branchmerge:
487 if branchmerge:
483 actions[standin] = ('k', None, 'replaced by non-standin')
488 actions[standin] = ('k', None, 'replaced by non-standin')
484 else:
489 else:
485 actions[standin] = ('r', None, 'replaced by non-standin')
490 actions[standin] = ('r', None, 'replaced by non-standin')
486 elif lm in ('g', 'dc') and sm != 'r':
491 elif lm in ('g', 'dc') and sm != 'r':
487 # Case 2: largefile in the working copy, normal file in
492 # Case 2: largefile in the working copy, normal file in
488 # the second parent
493 # the second parent
489 usermsg = _('remote turned local largefile %s into a normal file\n'
494 usermsg = _('remote turned local largefile %s into a normal file\n'
490 'keep (l)argefile or use (n)ormal file?'
495 'keep (l)argefile or use (n)ormal file?'
491 '$$ &Largefile $$ &Normal file') % lfile
496 '$$ &Largefile $$ &Normal file') % lfile
492 if repo.ui.promptchoice(usermsg, 0) == 0: # keep local largefile
497 if repo.ui.promptchoice(usermsg, 0) == 0: # keep local largefile
493 if branchmerge:
498 if branchmerge:
494 # largefile can be restored from standin safely
499 # largefile can be restored from standin safely
495 actions[lfile] = ('k', None, 'replaced by standin')
500 actions[lfile] = ('k', None, 'replaced by standin')
496 actions[standin] = ('k', None, 'replaces standin')
501 actions[standin] = ('k', None, 'replaces standin')
497 else:
502 else:
498 # "lfile" should be marked as "removed" without
503 # "lfile" should be marked as "removed" without
499 # removal of itself
504 # removal of itself
500 actions[lfile] = ('lfmr', None,
505 actions[lfile] = ('lfmr', None,
501 'forget non-standin largefile')
506 'forget non-standin largefile')
502
507
503 # linear-merge should treat this largefile as 're-added'
508 # linear-merge should treat this largefile as 're-added'
504 actions[standin] = ('a', None, 'keep standin')
509 actions[standin] = ('a', None, 'keep standin')
505 else: # pick remote normal file
510 else: # pick remote normal file
506 actions[lfile] = ('g', largs, 'replaces standin')
511 actions[lfile] = ('g', largs, 'replaces standin')
507 actions[standin] = ('r', None, 'replaced by non-standin')
512 actions[standin] = ('r', None, 'replaced by non-standin')
508
513
509 return actions, diverge, renamedelete
514 return actions, diverge, renamedelete
510
515
511 def mergerecordupdates(orig, repo, actions, branchmerge):
516 def mergerecordupdates(orig, repo, actions, branchmerge):
512 if 'lfmr' in actions:
517 if 'lfmr' in actions:
513 lfdirstate = lfutil.openlfdirstate(repo.ui, repo)
518 lfdirstate = lfutil.openlfdirstate(repo.ui, repo)
514 for lfile, args, msg in actions['lfmr']:
519 for lfile, args, msg in actions['lfmr']:
515 # this should be executed before 'orig', to execute 'remove'
520 # this should be executed before 'orig', to execute 'remove'
516 # before all other actions
521 # before all other actions
517 repo.dirstate.remove(lfile)
522 repo.dirstate.remove(lfile)
518 # make sure lfile doesn't get synclfdirstate'd as normal
523 # make sure lfile doesn't get synclfdirstate'd as normal
519 lfdirstate.add(lfile)
524 lfdirstate.add(lfile)
520 lfdirstate.write()
525 lfdirstate.write()
521
526
522 return orig(repo, actions, branchmerge)
527 return orig(repo, actions, branchmerge)
523
528
524
529
525 # Override filemerge to prompt the user about how they wish to merge
530 # Override filemerge to prompt the user about how they wish to merge
526 # largefiles. This will handle identical edits without prompting the user.
531 # largefiles. This will handle identical edits without prompting the user.
527 def overridefilemerge(origfn, repo, mynode, orig, fcd, fco, fca, labels=None):
532 def overridefilemerge(origfn, repo, mynode, orig, fcd, fco, fca, labels=None):
528 if not lfutil.isstandin(orig):
533 if not lfutil.isstandin(orig):
529 return origfn(repo, mynode, orig, fcd, fco, fca, labels=labels)
534 return origfn(repo, mynode, orig, fcd, fco, fca, labels=labels)
530
535
531 ahash = fca.data().strip().lower()
536 ahash = fca.data().strip().lower()
532 dhash = fcd.data().strip().lower()
537 dhash = fcd.data().strip().lower()
533 ohash = fco.data().strip().lower()
538 ohash = fco.data().strip().lower()
534 if (ohash != ahash and
539 if (ohash != ahash and
535 ohash != dhash and
540 ohash != dhash and
536 (dhash == ahash or
541 (dhash == ahash or
537 repo.ui.promptchoice(
542 repo.ui.promptchoice(
538 _('largefile %s has a merge conflict\nancestor was %s\n'
543 _('largefile %s has a merge conflict\nancestor was %s\n'
539 'keep (l)ocal %s or\ntake (o)ther %s?'
544 'keep (l)ocal %s or\ntake (o)ther %s?'
540 '$$ &Local $$ &Other') %
545 '$$ &Local $$ &Other') %
541 (lfutil.splitstandin(orig), ahash, dhash, ohash),
546 (lfutil.splitstandin(orig), ahash, dhash, ohash),
542 0) == 1)):
547 0) == 1)):
543 repo.wwrite(fcd.path(), fco.data(), fco.flags())
548 repo.wwrite(fcd.path(), fco.data(), fco.flags())
544 return 0
549 return 0
545
550
546 # Copy first changes the matchers to match standins instead of
551 # Copy first changes the matchers to match standins instead of
547 # largefiles. Then it overrides util.copyfile in that function it
552 # largefiles. Then it overrides util.copyfile in that function it
548 # checks if the destination largefile already exists. It also keeps a
553 # checks if the destination largefile already exists. It also keeps a
549 # list of copied files so that the largefiles can be copied and the
554 # list of copied files so that the largefiles can be copied and the
550 # dirstate updated.
555 # dirstate updated.
551 def overridecopy(orig, ui, repo, pats, opts, rename=False):
556 def overridecopy(orig, ui, repo, pats, opts, rename=False):
552 # doesn't remove largefile on rename
557 # doesn't remove largefile on rename
553 if len(pats) < 2:
558 if len(pats) < 2:
554 # this isn't legal, let the original function deal with it
559 # this isn't legal, let the original function deal with it
555 return orig(ui, repo, pats, opts, rename)
560 return orig(ui, repo, pats, opts, rename)
556
561
557 def makestandin(relpath):
562 def makestandin(relpath):
558 path = pathutil.canonpath(repo.root, repo.getcwd(), relpath)
563 path = pathutil.canonpath(repo.root, repo.getcwd(), relpath)
559 return os.path.join(repo.wjoin(lfutil.standin(path)))
564 return os.path.join(repo.wjoin(lfutil.standin(path)))
560
565
561 fullpats = scmutil.expandpats(pats)
566 fullpats = scmutil.expandpats(pats)
562 dest = fullpats[-1]
567 dest = fullpats[-1]
563
568
564 if os.path.isdir(dest):
569 if os.path.isdir(dest):
565 if not os.path.isdir(makestandin(dest)):
570 if not os.path.isdir(makestandin(dest)):
566 os.makedirs(makestandin(dest))
571 os.makedirs(makestandin(dest))
567 # This could copy both lfiles and normal files in one command,
572 # This could copy both lfiles and normal files in one command,
568 # but we don't want to do that. First replace their matcher to
573 # but we don't want to do that. First replace their matcher to
569 # only match normal files and run it, then replace it to just
574 # only match normal files and run it, then replace it to just
570 # match largefiles and run it again.
575 # match largefiles and run it again.
571 nonormalfiles = False
576 nonormalfiles = False
572 nolfiles = False
577 nolfiles = False
573 installnormalfilesmatchfn(repo[None].manifest())
578 installnormalfilesmatchfn(repo[None].manifest())
574 try:
579 try:
575 try:
580 try:
576 result = orig(ui, repo, pats, opts, rename)
581 result = orig(ui, repo, pats, opts, rename)
577 except util.Abort, e:
582 except util.Abort, e:
578 if str(e) != _('no files to copy'):
583 if str(e) != _('no files to copy'):
579 raise e
584 raise e
580 else:
585 else:
581 nonormalfiles = True
586 nonormalfiles = True
582 result = 0
587 result = 0
583 finally:
588 finally:
584 restorematchfn()
589 restorematchfn()
585
590
586 # The first rename can cause our current working directory to be removed.
591 # The first rename can cause our current working directory to be removed.
587 # In that case there is nothing left to copy/rename so just quit.
592 # In that case there is nothing left to copy/rename so just quit.
588 try:
593 try:
589 repo.getcwd()
594 repo.getcwd()
590 except OSError:
595 except OSError:
591 return result
596 return result
592
597
593 try:
598 try:
594 try:
599 try:
595 # When we call orig below it creates the standins but we don't add
600 # When we call orig below it creates the standins but we don't add
596 # them to the dir state until later so lock during that time.
601 # them to the dir state until later so lock during that time.
597 wlock = repo.wlock()
602 wlock = repo.wlock()
598
603
599 manifest = repo[None].manifest()
604 manifest = repo[None].manifest()
600 def overridematch(ctx, pats=[], opts={}, globbed=False,
605 def overridematch(ctx, pats=[], opts={}, globbed=False,
601 default='relpath'):
606 default='relpath'):
602 newpats = []
607 newpats = []
603 # The patterns were previously mangled to add the standin
608 # The patterns were previously mangled to add the standin
604 # directory; we need to remove that now
609 # directory; we need to remove that now
605 for pat in pats:
610 for pat in pats:
606 if match_.patkind(pat) is None and lfutil.shortname in pat:
611 if match_.patkind(pat) is None and lfutil.shortname in pat:
607 newpats.append(pat.replace(lfutil.shortname, ''))
612 newpats.append(pat.replace(lfutil.shortname, ''))
608 else:
613 else:
609 newpats.append(pat)
614 newpats.append(pat)
610 match = oldmatch(ctx, newpats, opts, globbed, default)
615 match = oldmatch(ctx, newpats, opts, globbed, default)
611 m = copy.copy(match)
616 m = copy.copy(match)
612 lfile = lambda f: lfutil.standin(f) in manifest
617 lfile = lambda f: lfutil.standin(f) in manifest
613 m._files = [lfutil.standin(f) for f in m._files if lfile(f)]
618 m._files = [lfutil.standin(f) for f in m._files if lfile(f)]
614 m._fmap = set(m._files)
619 m._fmap = set(m._files)
615 origmatchfn = m.matchfn
620 origmatchfn = m.matchfn
616 m.matchfn = lambda f: (lfutil.isstandin(f) and
621 m.matchfn = lambda f: (lfutil.isstandin(f) and
617 (f in manifest) and
622 (f in manifest) and
618 origmatchfn(lfutil.splitstandin(f)) or
623 origmatchfn(lfutil.splitstandin(f)) or
619 None)
624 None)
620 return m
625 return m
621 oldmatch = installmatchfn(overridematch)
626 oldmatch = installmatchfn(overridematch)
622 listpats = []
627 listpats = []
623 for pat in pats:
628 for pat in pats:
624 if match_.patkind(pat) is not None:
629 if match_.patkind(pat) is not None:
625 listpats.append(pat)
630 listpats.append(pat)
626 else:
631 else:
627 listpats.append(makestandin(pat))
632 listpats.append(makestandin(pat))
628
633
629 try:
634 try:
630 origcopyfile = util.copyfile
635 origcopyfile = util.copyfile
631 copiedfiles = []
636 copiedfiles = []
632 def overridecopyfile(src, dest):
637 def overridecopyfile(src, dest):
633 if (lfutil.shortname in src and
638 if (lfutil.shortname in src and
634 dest.startswith(repo.wjoin(lfutil.shortname))):
639 dest.startswith(repo.wjoin(lfutil.shortname))):
635 destlfile = dest.replace(lfutil.shortname, '')
640 destlfile = dest.replace(lfutil.shortname, '')
636 if not opts['force'] and os.path.exists(destlfile):
641 if not opts['force'] and os.path.exists(destlfile):
637 raise IOError('',
642 raise IOError('',
638 _('destination largefile already exists'))
643 _('destination largefile already exists'))
639 copiedfiles.append((src, dest))
644 copiedfiles.append((src, dest))
640 origcopyfile(src, dest)
645 origcopyfile(src, dest)
641
646
642 util.copyfile = overridecopyfile
647 util.copyfile = overridecopyfile
643 result += orig(ui, repo, listpats, opts, rename)
648 result += orig(ui, repo, listpats, opts, rename)
644 finally:
649 finally:
645 util.copyfile = origcopyfile
650 util.copyfile = origcopyfile
646
651
647 lfdirstate = lfutil.openlfdirstate(ui, repo)
652 lfdirstate = lfutil.openlfdirstate(ui, repo)
648 for (src, dest) in copiedfiles:
653 for (src, dest) in copiedfiles:
649 if (lfutil.shortname in src and
654 if (lfutil.shortname in src and
650 dest.startswith(repo.wjoin(lfutil.shortname))):
655 dest.startswith(repo.wjoin(lfutil.shortname))):
651 srclfile = src.replace(repo.wjoin(lfutil.standin('')), '')
656 srclfile = src.replace(repo.wjoin(lfutil.standin('')), '')
652 destlfile = dest.replace(repo.wjoin(lfutil.standin('')), '')
657 destlfile = dest.replace(repo.wjoin(lfutil.standin('')), '')
653 destlfiledir = os.path.dirname(repo.wjoin(destlfile)) or '.'
658 destlfiledir = os.path.dirname(repo.wjoin(destlfile)) or '.'
654 if not os.path.isdir(destlfiledir):
659 if not os.path.isdir(destlfiledir):
655 os.makedirs(destlfiledir)
660 os.makedirs(destlfiledir)
656 if rename:
661 if rename:
657 os.rename(repo.wjoin(srclfile), repo.wjoin(destlfile))
662 os.rename(repo.wjoin(srclfile), repo.wjoin(destlfile))
658
663
659 # The file is gone, but this deletes any empty parent
664 # The file is gone, but this deletes any empty parent
660 # directories as a side-effect.
665 # directories as a side-effect.
661 util.unlinkpath(repo.wjoin(srclfile), True)
666 util.unlinkpath(repo.wjoin(srclfile), True)
662 lfdirstate.remove(srclfile)
667 lfdirstate.remove(srclfile)
663 else:
668 else:
664 util.copyfile(repo.wjoin(srclfile),
669 util.copyfile(repo.wjoin(srclfile),
665 repo.wjoin(destlfile))
670 repo.wjoin(destlfile))
666
671
667 lfdirstate.add(destlfile)
672 lfdirstate.add(destlfile)
668 lfdirstate.write()
673 lfdirstate.write()
669 except util.Abort, e:
674 except util.Abort, e:
670 if str(e) != _('no files to copy'):
675 if str(e) != _('no files to copy'):
671 raise e
676 raise e
672 else:
677 else:
673 nolfiles = True
678 nolfiles = True
674 finally:
679 finally:
675 restorematchfn()
680 restorematchfn()
676 wlock.release()
681 wlock.release()
677
682
678 if nolfiles and nonormalfiles:
683 if nolfiles and nonormalfiles:
679 raise util.Abort(_('no files to copy'))
684 raise util.Abort(_('no files to copy'))
680
685
681 return result
686 return result
682
687
683 # When the user calls revert, we have to be careful to not revert any
688 # When the user calls revert, we have to be careful to not revert any
684 # changes to other largefiles accidentally. This means we have to keep
689 # changes to other largefiles accidentally. This means we have to keep
685 # track of the largefiles that are being reverted so we only pull down
690 # track of the largefiles that are being reverted so we only pull down
686 # the necessary largefiles.
691 # the necessary largefiles.
687 #
692 #
688 # Standins are only updated (to match the hash of largefiles) before
693 # Standins are only updated (to match the hash of largefiles) before
689 # commits. Update the standins then run the original revert, changing
694 # commits. Update the standins then run the original revert, changing
690 # the matcher to hit standins instead of largefiles. Based on the
695 # the matcher to hit standins instead of largefiles. Based on the
691 # resulting standins update the largefiles.
696 # resulting standins update the largefiles.
692 def overriderevert(orig, ui, repo, *pats, **opts):
697 def overriderevert(orig, ui, repo, *pats, **opts):
693 # Because we put the standins in a bad state (by updating them)
698 # Because we put the standins in a bad state (by updating them)
694 # and then return them to a correct state we need to lock to
699 # and then return them to a correct state we need to lock to
695 # prevent others from changing them in their incorrect state.
700 # prevent others from changing them in their incorrect state.
696 wlock = repo.wlock()
701 wlock = repo.wlock()
697 try:
702 try:
698 lfdirstate = lfutil.openlfdirstate(ui, repo)
703 lfdirstate = lfutil.openlfdirstate(ui, repo)
699 s = lfutil.lfdirstatestatus(lfdirstate, repo)
704 s = lfutil.lfdirstatestatus(lfdirstate, repo)
700 lfdirstate.write()
705 lfdirstate.write()
701 for lfile in s.modified:
706 for lfile in s.modified:
702 lfutil.updatestandin(repo, lfutil.standin(lfile))
707 lfutil.updatestandin(repo, lfutil.standin(lfile))
703 for lfile in s.deleted:
708 for lfile in s.deleted:
704 if (os.path.exists(repo.wjoin(lfutil.standin(lfile)))):
709 if (os.path.exists(repo.wjoin(lfutil.standin(lfile)))):
705 os.unlink(repo.wjoin(lfutil.standin(lfile)))
710 os.unlink(repo.wjoin(lfutil.standin(lfile)))
706
711
707 oldstandins = lfutil.getstandinsstate(repo)
712 oldstandins = lfutil.getstandinsstate(repo)
708
713
709 def overridematch(ctx, pats=[], opts={}, globbed=False,
714 def overridematch(ctx, pats=[], opts={}, globbed=False,
710 default='relpath'):
715 default='relpath'):
711 match = oldmatch(ctx, pats, opts, globbed, default)
716 match = oldmatch(ctx, pats, opts, globbed, default)
712 m = copy.copy(match)
717 m = copy.copy(match)
713 def tostandin(f):
718 def tostandin(f):
714 if lfutil.standin(f) in ctx:
719 if lfutil.standin(f) in ctx:
715 return lfutil.standin(f)
720 return lfutil.standin(f)
716 elif lfutil.standin(f) in repo[None]:
721 elif lfutil.standin(f) in repo[None]:
717 return None
722 return None
718 return f
723 return f
719 m._files = [tostandin(f) for f in m._files]
724 m._files = [tostandin(f) for f in m._files]
720 m._files = [f for f in m._files if f is not None]
725 m._files = [f for f in m._files if f is not None]
721 m._fmap = set(m._files)
726 m._fmap = set(m._files)
722 origmatchfn = m.matchfn
727 origmatchfn = m.matchfn
723 def matchfn(f):
728 def matchfn(f):
724 if lfutil.isstandin(f):
729 if lfutil.isstandin(f):
725 return (origmatchfn(lfutil.splitstandin(f)) and
730 return (origmatchfn(lfutil.splitstandin(f)) and
726 (f in repo[None] or f in ctx))
731 (f in repo[None] or f in ctx))
727 return origmatchfn(f)
732 return origmatchfn(f)
728 m.matchfn = matchfn
733 m.matchfn = matchfn
729 return m
734 return m
730 oldmatch = installmatchfn(overridematch)
735 oldmatch = installmatchfn(overridematch)
731 try:
736 try:
732 orig(ui, repo, *pats, **opts)
737 orig(ui, repo, *pats, **opts)
733 finally:
738 finally:
734 restorematchfn()
739 restorematchfn()
735
740
736 newstandins = lfutil.getstandinsstate(repo)
741 newstandins = lfutil.getstandinsstate(repo)
737 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
742 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
738 # lfdirstate should be 'normallookup'-ed for updated files,
743 # lfdirstate should be 'normallookup'-ed for updated files,
739 # because reverting doesn't touch dirstate for 'normal' files
744 # because reverting doesn't touch dirstate for 'normal' files
740 # when target revision is explicitly specified: in such case,
745 # when target revision is explicitly specified: in such case,
741 # 'n' and valid timestamp in dirstate doesn't ensure 'clean'
746 # 'n' and valid timestamp in dirstate doesn't ensure 'clean'
742 # of target (standin) file.
747 # of target (standin) file.
743 lfcommands.updatelfiles(ui, repo, filelist, printmessage=False,
748 lfcommands.updatelfiles(ui, repo, filelist, printmessage=False,
744 normallookup=True)
749 normallookup=True)
745
750
746 finally:
751 finally:
747 wlock.release()
752 wlock.release()
748
753
749 # after pulling changesets, we need to take some extra care to get
754 # after pulling changesets, we need to take some extra care to get
750 # largefiles updated remotely
755 # largefiles updated remotely
751 def overridepull(orig, ui, repo, source=None, **opts):
756 def overridepull(orig, ui, repo, source=None, **opts):
752 revsprepull = len(repo)
757 revsprepull = len(repo)
753 if not source:
758 if not source:
754 source = 'default'
759 source = 'default'
755 repo.lfpullsource = source
760 repo.lfpullsource = source
756 result = orig(ui, repo, source, **opts)
761 result = orig(ui, repo, source, **opts)
757 revspostpull = len(repo)
762 revspostpull = len(repo)
758 lfrevs = opts.get('lfrev', [])
763 lfrevs = opts.get('lfrev', [])
759 if opts.get('all_largefiles'):
764 if opts.get('all_largefiles'):
760 lfrevs.append('pulled()')
765 lfrevs.append('pulled()')
761 if lfrevs and revspostpull > revsprepull:
766 if lfrevs and revspostpull > revsprepull:
762 numcached = 0
767 numcached = 0
763 repo.firstpulled = revsprepull # for pulled() revset expression
768 repo.firstpulled = revsprepull # for pulled() revset expression
764 try:
769 try:
765 for rev in scmutil.revrange(repo, lfrevs):
770 for rev in scmutil.revrange(repo, lfrevs):
766 ui.note(_('pulling largefiles for revision %s\n') % rev)
771 ui.note(_('pulling largefiles for revision %s\n') % rev)
767 (cached, missing) = lfcommands.cachelfiles(ui, repo, rev)
772 (cached, missing) = lfcommands.cachelfiles(ui, repo, rev)
768 numcached += len(cached)
773 numcached += len(cached)
769 finally:
774 finally:
770 del repo.firstpulled
775 del repo.firstpulled
771 ui.status(_("%d largefiles cached\n") % numcached)
776 ui.status(_("%d largefiles cached\n") % numcached)
772 return result
777 return result
773
778
774 def pulledrevsetsymbol(repo, subset, x):
779 def pulledrevsetsymbol(repo, subset, x):
775 """``pulled()``
780 """``pulled()``
776 Changesets that just has been pulled.
781 Changesets that just has been pulled.
777
782
778 Only available with largefiles from pull --lfrev expressions.
783 Only available with largefiles from pull --lfrev expressions.
779
784
780 .. container:: verbose
785 .. container:: verbose
781
786
782 Some examples:
787 Some examples:
783
788
784 - pull largefiles for all new changesets::
789 - pull largefiles for all new changesets::
785
790
786 hg pull -lfrev "pulled()"
791 hg pull -lfrev "pulled()"
787
792
788 - pull largefiles for all new branch heads::
793 - pull largefiles for all new branch heads::
789
794
790 hg pull -lfrev "head(pulled()) and not closed()"
795 hg pull -lfrev "head(pulled()) and not closed()"
791
796
792 """
797 """
793
798
794 try:
799 try:
795 firstpulled = repo.firstpulled
800 firstpulled = repo.firstpulled
796 except AttributeError:
801 except AttributeError:
797 raise util.Abort(_("pulled() only available in --lfrev"))
802 raise util.Abort(_("pulled() only available in --lfrev"))
798 return revset.baseset([r for r in subset if r >= firstpulled])
803 return revset.baseset([r for r in subset if r >= firstpulled])
799
804
800 def overrideclone(orig, ui, source, dest=None, **opts):
805 def overrideclone(orig, ui, source, dest=None, **opts):
801 d = dest
806 d = dest
802 if d is None:
807 if d is None:
803 d = hg.defaultdest(source)
808 d = hg.defaultdest(source)
804 if opts.get('all_largefiles') and not hg.islocal(d):
809 if opts.get('all_largefiles') and not hg.islocal(d):
805 raise util.Abort(_(
810 raise util.Abort(_(
806 '--all-largefiles is incompatible with non-local destination %s') %
811 '--all-largefiles is incompatible with non-local destination %s') %
807 d)
812 d)
808
813
809 return orig(ui, source, dest, **opts)
814 return orig(ui, source, dest, **opts)
810
815
811 def hgclone(orig, ui, opts, *args, **kwargs):
816 def hgclone(orig, ui, opts, *args, **kwargs):
812 result = orig(ui, opts, *args, **kwargs)
817 result = orig(ui, opts, *args, **kwargs)
813
818
814 if result is not None:
819 if result is not None:
815 sourcerepo, destrepo = result
820 sourcerepo, destrepo = result
816 repo = destrepo.local()
821 repo = destrepo.local()
817
822
818 # Caching is implicitly limited to 'rev' option, since the dest repo was
823 # Caching is implicitly limited to 'rev' option, since the dest repo was
819 # truncated at that point. The user may expect a download count with
824 # truncated at that point. The user may expect a download count with
820 # this option, so attempt whether or not this is a largefile repo.
825 # this option, so attempt whether or not this is a largefile repo.
821 if opts.get('all_largefiles'):
826 if opts.get('all_largefiles'):
822 success, missing = lfcommands.downloadlfiles(ui, repo, None)
827 success, missing = lfcommands.downloadlfiles(ui, repo, None)
823
828
824 if missing != 0:
829 if missing != 0:
825 return None
830 return None
826
831
827 return result
832 return result
828
833
829 def overriderebase(orig, ui, repo, **opts):
834 def overriderebase(orig, ui, repo, **opts):
830 resuming = opts.get('continue')
835 resuming = opts.get('continue')
831 repo._lfcommithooks.append(lfutil.automatedcommithook(resuming))
836 repo._lfcommithooks.append(lfutil.automatedcommithook(resuming))
832 repo._lfstatuswriters.append(lambda *msg, **opts: None)
837 repo._lfstatuswriters.append(lambda *msg, **opts: None)
833 try:
838 try:
834 return orig(ui, repo, **opts)
839 return orig(ui, repo, **opts)
835 finally:
840 finally:
836 repo._lfstatuswriters.pop()
841 repo._lfstatuswriters.pop()
837 repo._lfcommithooks.pop()
842 repo._lfcommithooks.pop()
838
843
839 def overridearchive(orig, repo, dest, node, kind, decode=True, matchfn=None,
844 def overridearchive(orig, repo, dest, node, kind, decode=True, matchfn=None,
840 prefix=None, mtime=None, subrepos=None):
845 prefix=None, mtime=None, subrepos=None):
841 # No need to lock because we are only reading history and
846 # No need to lock because we are only reading history and
842 # largefile caches, neither of which are modified.
847 # largefile caches, neither of which are modified.
843 lfcommands.cachelfiles(repo.ui, repo, node)
848 lfcommands.cachelfiles(repo.ui, repo, node)
844
849
845 if kind not in archival.archivers:
850 if kind not in archival.archivers:
846 raise util.Abort(_("unknown archive type '%s'") % kind)
851 raise util.Abort(_("unknown archive type '%s'") % kind)
847
852
848 ctx = repo[node]
853 ctx = repo[node]
849
854
850 if kind == 'files':
855 if kind == 'files':
851 if prefix:
856 if prefix:
852 raise util.Abort(
857 raise util.Abort(
853 _('cannot give prefix when archiving to files'))
858 _('cannot give prefix when archiving to files'))
854 else:
859 else:
855 prefix = archival.tidyprefix(dest, kind, prefix)
860 prefix = archival.tidyprefix(dest, kind, prefix)
856
861
857 def write(name, mode, islink, getdata):
862 def write(name, mode, islink, getdata):
858 if matchfn and not matchfn(name):
863 if matchfn and not matchfn(name):
859 return
864 return
860 data = getdata()
865 data = getdata()
861 if decode:
866 if decode:
862 data = repo.wwritedata(name, data)
867 data = repo.wwritedata(name, data)
863 archiver.addfile(prefix + name, mode, islink, data)
868 archiver.addfile(prefix + name, mode, islink, data)
864
869
865 archiver = archival.archivers[kind](dest, mtime or ctx.date()[0])
870 archiver = archival.archivers[kind](dest, mtime or ctx.date()[0])
866
871
867 if repo.ui.configbool("ui", "archivemeta", True):
872 if repo.ui.configbool("ui", "archivemeta", True):
868 def metadata():
873 def metadata():
869 base = 'repo: %s\nnode: %s\nbranch: %s\n' % (
874 base = 'repo: %s\nnode: %s\nbranch: %s\n' % (
870 hex(repo.changelog.node(0)), hex(node), ctx.branch())
875 hex(repo.changelog.node(0)), hex(node), ctx.branch())
871
876
872 tags = ''.join('tag: %s\n' % t for t in ctx.tags()
877 tags = ''.join('tag: %s\n' % t for t in ctx.tags()
873 if repo.tagtype(t) == 'global')
878 if repo.tagtype(t) == 'global')
874 if not tags:
879 if not tags:
875 repo.ui.pushbuffer()
880 repo.ui.pushbuffer()
876 opts = {'template': '{latesttag}\n{latesttagdistance}',
881 opts = {'template': '{latesttag}\n{latesttagdistance}',
877 'style': '', 'patch': None, 'git': None}
882 'style': '', 'patch': None, 'git': None}
878 cmdutil.show_changeset(repo.ui, repo, opts).show(ctx)
883 cmdutil.show_changeset(repo.ui, repo, opts).show(ctx)
879 ltags, dist = repo.ui.popbuffer().split('\n')
884 ltags, dist = repo.ui.popbuffer().split('\n')
880 tags = ''.join('latesttag: %s\n' % t for t in ltags.split(':'))
885 tags = ''.join('latesttag: %s\n' % t for t in ltags.split(':'))
881 tags += 'latesttagdistance: %s\n' % dist
886 tags += 'latesttagdistance: %s\n' % dist
882
887
883 return base + tags
888 return base + tags
884
889
885 write('.hg_archival.txt', 0644, False, metadata)
890 write('.hg_archival.txt', 0644, False, metadata)
886
891
887 for f in ctx:
892 for f in ctx:
888 ff = ctx.flags(f)
893 ff = ctx.flags(f)
889 getdata = ctx[f].data
894 getdata = ctx[f].data
890 if lfutil.isstandin(f):
895 if lfutil.isstandin(f):
891 path = lfutil.findfile(repo, getdata().strip())
896 path = lfutil.findfile(repo, getdata().strip())
892 if path is None:
897 if path is None:
893 raise util.Abort(
898 raise util.Abort(
894 _('largefile %s not found in repo store or system cache')
899 _('largefile %s not found in repo store or system cache')
895 % lfutil.splitstandin(f))
900 % lfutil.splitstandin(f))
896 f = lfutil.splitstandin(f)
901 f = lfutil.splitstandin(f)
897
902
898 def getdatafn():
903 def getdatafn():
899 fd = None
904 fd = None
900 try:
905 try:
901 fd = open(path, 'rb')
906 fd = open(path, 'rb')
902 return fd.read()
907 return fd.read()
903 finally:
908 finally:
904 if fd:
909 if fd:
905 fd.close()
910 fd.close()
906
911
907 getdata = getdatafn
912 getdata = getdatafn
908 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
913 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
909
914
910 if subrepos:
915 if subrepos:
911 for subpath in sorted(ctx.substate):
916 for subpath in sorted(ctx.substate):
912 sub = ctx.sub(subpath)
917 sub = ctx.sub(subpath)
913 submatch = match_.narrowmatcher(subpath, matchfn)
918 submatch = match_.narrowmatcher(subpath, matchfn)
914 sub.archive(archiver, prefix, submatch)
919 sub.archive(archiver, prefix, submatch)
915
920
916 archiver.done()
921 archiver.done()
917
922
918 def hgsubrepoarchive(orig, repo, archiver, prefix, match=None):
923 def hgsubrepoarchive(orig, repo, archiver, prefix, match=None):
919 repo._get(repo._state + ('hg',))
924 repo._get(repo._state + ('hg',))
920 rev = repo._state[1]
925 rev = repo._state[1]
921 ctx = repo._repo[rev]
926 ctx = repo._repo[rev]
922
927
923 lfcommands.cachelfiles(repo.ui, repo._repo, ctx.node())
928 lfcommands.cachelfiles(repo.ui, repo._repo, ctx.node())
924
929
925 def write(name, mode, islink, getdata):
930 def write(name, mode, islink, getdata):
926 # At this point, the standin has been replaced with the largefile name,
931 # At this point, the standin has been replaced with the largefile name,
927 # so the normal matcher works here without the lfutil variants.
932 # so the normal matcher works here without the lfutil variants.
928 if match and not match(f):
933 if match and not match(f):
929 return
934 return
930 data = getdata()
935 data = getdata()
931
936
932 archiver.addfile(prefix + repo._path + '/' + name, mode, islink, data)
937 archiver.addfile(prefix + repo._path + '/' + name, mode, islink, data)
933
938
934 for f in ctx:
939 for f in ctx:
935 ff = ctx.flags(f)
940 ff = ctx.flags(f)
936 getdata = ctx[f].data
941 getdata = ctx[f].data
937 if lfutil.isstandin(f):
942 if lfutil.isstandin(f):
938 path = lfutil.findfile(repo._repo, getdata().strip())
943 path = lfutil.findfile(repo._repo, getdata().strip())
939 if path is None:
944 if path is None:
940 raise util.Abort(
945 raise util.Abort(
941 _('largefile %s not found in repo store or system cache')
946 _('largefile %s not found in repo store or system cache')
942 % lfutil.splitstandin(f))
947 % lfutil.splitstandin(f))
943 f = lfutil.splitstandin(f)
948 f = lfutil.splitstandin(f)
944
949
945 def getdatafn():
950 def getdatafn():
946 fd = None
951 fd = None
947 try:
952 try:
948 fd = open(os.path.join(prefix, path), 'rb')
953 fd = open(os.path.join(prefix, path), 'rb')
949 return fd.read()
954 return fd.read()
950 finally:
955 finally:
951 if fd:
956 if fd:
952 fd.close()
957 fd.close()
953
958
954 getdata = getdatafn
959 getdata = getdatafn
955
960
956 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
961 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
957
962
958 for subpath in sorted(ctx.substate):
963 for subpath in sorted(ctx.substate):
959 sub = ctx.sub(subpath)
964 sub = ctx.sub(subpath)
960 submatch = match_.narrowmatcher(subpath, match)
965 submatch = match_.narrowmatcher(subpath, match)
961 sub.archive(archiver, os.path.join(prefix, repo._path) + '/', submatch)
966 sub.archive(archiver, os.path.join(prefix, repo._path) + '/', submatch)
962
967
963 # If a largefile is modified, the change is not reflected in its
968 # If a largefile is modified, the change is not reflected in its
964 # standin until a commit. cmdutil.bailifchanged() raises an exception
969 # standin until a commit. cmdutil.bailifchanged() raises an exception
965 # if the repo has uncommitted changes. Wrap it to also check if
970 # if the repo has uncommitted changes. Wrap it to also check if
966 # largefiles were changed. This is used by bisect, backout and fetch.
971 # largefiles were changed. This is used by bisect, backout and fetch.
967 def overridebailifchanged(orig, repo):
972 def overridebailifchanged(orig, repo):
968 orig(repo)
973 orig(repo)
969 repo.lfstatus = True
974 repo.lfstatus = True
970 s = repo.status()
975 s = repo.status()
971 repo.lfstatus = False
976 repo.lfstatus = False
972 if s.modified or s.added or s.removed or s.deleted:
977 if s.modified or s.added or s.removed or s.deleted:
973 raise util.Abort(_('uncommitted changes'))
978 raise util.Abort(_('uncommitted changes'))
974
979
975 def cmdutilforget(orig, ui, repo, match, prefix, explicitonly):
980 def cmdutilforget(orig, ui, repo, match, prefix, explicitonly):
976 normalmatcher = composenormalfilematcher(match, repo[None].manifest())
981 normalmatcher = composenormalfilematcher(match, repo[None].manifest())
977 bad, forgot = orig(ui, repo, normalmatcher, prefix, explicitonly)
982 bad, forgot = orig(ui, repo, normalmatcher, prefix, explicitonly)
978 m = composelargefilematcher(match, repo[None].manifest())
983 m = composelargefilematcher(match, repo[None].manifest())
979
984
980 try:
985 try:
981 repo.lfstatus = True
986 repo.lfstatus = True
982 s = repo.status(match=m, clean=True)
987 s = repo.status(match=m, clean=True)
983 finally:
988 finally:
984 repo.lfstatus = False
989 repo.lfstatus = False
985 forget = sorted(s.modified + s.added + s.deleted + s.clean)
990 forget = sorted(s.modified + s.added + s.deleted + s.clean)
986 forget = [f for f in forget if lfutil.standin(f) in repo[None].manifest()]
991 forget = [f for f in forget if lfutil.standin(f) in repo[None].manifest()]
987
992
988 for f in forget:
993 for f in forget:
989 if lfutil.standin(f) not in repo.dirstate and not \
994 if lfutil.standin(f) not in repo.dirstate and not \
990 repo.wvfs.isdir(lfutil.standin(f)):
995 repo.wvfs.isdir(lfutil.standin(f)):
991 ui.warn(_('not removing %s: file is already untracked\n')
996 ui.warn(_('not removing %s: file is already untracked\n')
992 % m.rel(f))
997 % m.rel(f))
993 bad.append(f)
998 bad.append(f)
994
999
995 for f in forget:
1000 for f in forget:
996 if ui.verbose or not m.exact(f):
1001 if ui.verbose or not m.exact(f):
997 ui.status(_('removing %s\n') % m.rel(f))
1002 ui.status(_('removing %s\n') % m.rel(f))
998
1003
999 # Need to lock because standin files are deleted then removed from the
1004 # Need to lock because standin files are deleted then removed from the
1000 # repository and we could race in-between.
1005 # repository and we could race in-between.
1001 wlock = repo.wlock()
1006 wlock = repo.wlock()
1002 try:
1007 try:
1003 lfdirstate = lfutil.openlfdirstate(ui, repo)
1008 lfdirstate = lfutil.openlfdirstate(ui, repo)
1004 for f in forget:
1009 for f in forget:
1005 if lfdirstate[f] == 'a':
1010 if lfdirstate[f] == 'a':
1006 lfdirstate.drop(f)
1011 lfdirstate.drop(f)
1007 else:
1012 else:
1008 lfdirstate.remove(f)
1013 lfdirstate.remove(f)
1009 lfdirstate.write()
1014 lfdirstate.write()
1010 standins = [lfutil.standin(f) for f in forget]
1015 standins = [lfutil.standin(f) for f in forget]
1011 for f in standins:
1016 for f in standins:
1012 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
1017 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
1013 rejected = repo[None].forget(standins)
1018 rejected = repo[None].forget(standins)
1014 finally:
1019 finally:
1015 wlock.release()
1020 wlock.release()
1016
1021
1017 bad.extend(f for f in rejected if f in m.files())
1022 bad.extend(f for f in rejected if f in m.files())
1018 forgot.extend(f for f in forget if f not in rejected)
1023 forgot.extend(f for f in forget if f not in rejected)
1019 return bad, forgot
1024 return bad, forgot
1020
1025
1021 def _getoutgoings(repo, other, missing, addfunc):
1026 def _getoutgoings(repo, other, missing, addfunc):
1022 """get pairs of filename and largefile hash in outgoing revisions
1027 """get pairs of filename and largefile hash in outgoing revisions
1023 in 'missing'.
1028 in 'missing'.
1024
1029
1025 largefiles already existing on 'other' repository are ignored.
1030 largefiles already existing on 'other' repository are ignored.
1026
1031
1027 'addfunc' is invoked with each unique pairs of filename and
1032 'addfunc' is invoked with each unique pairs of filename and
1028 largefile hash value.
1033 largefile hash value.
1029 """
1034 """
1030 knowns = set()
1035 knowns = set()
1031 lfhashes = set()
1036 lfhashes = set()
1032 def dedup(fn, lfhash):
1037 def dedup(fn, lfhash):
1033 k = (fn, lfhash)
1038 k = (fn, lfhash)
1034 if k not in knowns:
1039 if k not in knowns:
1035 knowns.add(k)
1040 knowns.add(k)
1036 lfhashes.add(lfhash)
1041 lfhashes.add(lfhash)
1037 lfutil.getlfilestoupload(repo, missing, dedup)
1042 lfutil.getlfilestoupload(repo, missing, dedup)
1038 if lfhashes:
1043 if lfhashes:
1039 lfexists = basestore._openstore(repo, other).exists(lfhashes)
1044 lfexists = basestore._openstore(repo, other).exists(lfhashes)
1040 for fn, lfhash in knowns:
1045 for fn, lfhash in knowns:
1041 if not lfexists[lfhash]: # lfhash doesn't exist on "other"
1046 if not lfexists[lfhash]: # lfhash doesn't exist on "other"
1042 addfunc(fn, lfhash)
1047 addfunc(fn, lfhash)
1043
1048
1044 def outgoinghook(ui, repo, other, opts, missing):
1049 def outgoinghook(ui, repo, other, opts, missing):
1045 if opts.pop('large', None):
1050 if opts.pop('large', None):
1046 lfhashes = set()
1051 lfhashes = set()
1047 if ui.debugflag:
1052 if ui.debugflag:
1048 toupload = {}
1053 toupload = {}
1049 def addfunc(fn, lfhash):
1054 def addfunc(fn, lfhash):
1050 if fn not in toupload:
1055 if fn not in toupload:
1051 toupload[fn] = []
1056 toupload[fn] = []
1052 toupload[fn].append(lfhash)
1057 toupload[fn].append(lfhash)
1053 lfhashes.add(lfhash)
1058 lfhashes.add(lfhash)
1054 def showhashes(fn):
1059 def showhashes(fn):
1055 for lfhash in sorted(toupload[fn]):
1060 for lfhash in sorted(toupload[fn]):
1056 ui.debug(' %s\n' % (lfhash))
1061 ui.debug(' %s\n' % (lfhash))
1057 else:
1062 else:
1058 toupload = set()
1063 toupload = set()
1059 def addfunc(fn, lfhash):
1064 def addfunc(fn, lfhash):
1060 toupload.add(fn)
1065 toupload.add(fn)
1061 lfhashes.add(lfhash)
1066 lfhashes.add(lfhash)
1062 def showhashes(fn):
1067 def showhashes(fn):
1063 pass
1068 pass
1064 _getoutgoings(repo, other, missing, addfunc)
1069 _getoutgoings(repo, other, missing, addfunc)
1065
1070
1066 if not toupload:
1071 if not toupload:
1067 ui.status(_('largefiles: no files to upload\n'))
1072 ui.status(_('largefiles: no files to upload\n'))
1068 else:
1073 else:
1069 ui.status(_('largefiles to upload (%d entities):\n')
1074 ui.status(_('largefiles to upload (%d entities):\n')
1070 % (len(lfhashes)))
1075 % (len(lfhashes)))
1071 for file in sorted(toupload):
1076 for file in sorted(toupload):
1072 ui.status(lfutil.splitstandin(file) + '\n')
1077 ui.status(lfutil.splitstandin(file) + '\n')
1073 showhashes(file)
1078 showhashes(file)
1074 ui.status('\n')
1079 ui.status('\n')
1075
1080
1076 def summaryremotehook(ui, repo, opts, changes):
1081 def summaryremotehook(ui, repo, opts, changes):
1077 largeopt = opts.get('large', False)
1082 largeopt = opts.get('large', False)
1078 if changes is None:
1083 if changes is None:
1079 if largeopt:
1084 if largeopt:
1080 return (False, True) # only outgoing check is needed
1085 return (False, True) # only outgoing check is needed
1081 else:
1086 else:
1082 return (False, False)
1087 return (False, False)
1083 elif largeopt:
1088 elif largeopt:
1084 url, branch, peer, outgoing = changes[1]
1089 url, branch, peer, outgoing = changes[1]
1085 if peer is None:
1090 if peer is None:
1086 # i18n: column positioning for "hg summary"
1091 # i18n: column positioning for "hg summary"
1087 ui.status(_('largefiles: (no remote repo)\n'))
1092 ui.status(_('largefiles: (no remote repo)\n'))
1088 return
1093 return
1089
1094
1090 toupload = set()
1095 toupload = set()
1091 lfhashes = set()
1096 lfhashes = set()
1092 def addfunc(fn, lfhash):
1097 def addfunc(fn, lfhash):
1093 toupload.add(fn)
1098 toupload.add(fn)
1094 lfhashes.add(lfhash)
1099 lfhashes.add(lfhash)
1095 _getoutgoings(repo, peer, outgoing.missing, addfunc)
1100 _getoutgoings(repo, peer, outgoing.missing, addfunc)
1096
1101
1097 if not toupload:
1102 if not toupload:
1098 # i18n: column positioning for "hg summary"
1103 # i18n: column positioning for "hg summary"
1099 ui.status(_('largefiles: (no files to upload)\n'))
1104 ui.status(_('largefiles: (no files to upload)\n'))
1100 else:
1105 else:
1101 # i18n: column positioning for "hg summary"
1106 # i18n: column positioning for "hg summary"
1102 ui.status(_('largefiles: %d entities for %d files to upload\n')
1107 ui.status(_('largefiles: %d entities for %d files to upload\n')
1103 % (len(lfhashes), len(toupload)))
1108 % (len(lfhashes), len(toupload)))
1104
1109
1105 def overridesummary(orig, ui, repo, *pats, **opts):
1110 def overridesummary(orig, ui, repo, *pats, **opts):
1106 try:
1111 try:
1107 repo.lfstatus = True
1112 repo.lfstatus = True
1108 orig(ui, repo, *pats, **opts)
1113 orig(ui, repo, *pats, **opts)
1109 finally:
1114 finally:
1110 repo.lfstatus = False
1115 repo.lfstatus = False
1111
1116
1112 def scmutiladdremove(orig, repo, matcher, prefix, opts={}, dry_run=None,
1117 def scmutiladdremove(orig, repo, matcher, prefix, opts={}, dry_run=None,
1113 similarity=None):
1118 similarity=None):
1114 if not lfutil.islfilesrepo(repo):
1119 if not lfutil.islfilesrepo(repo):
1115 return orig(repo, matcher, prefix, opts, dry_run, similarity)
1120 return orig(repo, matcher, prefix, opts, dry_run, similarity)
1116 # Get the list of missing largefiles so we can remove them
1121 # Get the list of missing largefiles so we can remove them
1117 lfdirstate = lfutil.openlfdirstate(repo.ui, repo)
1122 lfdirstate = lfutil.openlfdirstate(repo.ui, repo)
1118 unsure, s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [],
1123 unsure, s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [],
1119 False, False, False)
1124 False, False, False)
1120
1125
1121 # Call into the normal remove code, but the removing of the standin, we want
1126 # Call into the normal remove code, but the removing of the standin, we want
1122 # to have handled by original addremove. Monkey patching here makes sure
1127 # to have handled by original addremove. Monkey patching here makes sure
1123 # we don't remove the standin in the largefiles code, preventing a very
1128 # we don't remove the standin in the largefiles code, preventing a very
1124 # confused state later.
1129 # confused state later.
1125 if s.deleted:
1130 if s.deleted:
1126 m = copy.copy(matcher)
1131 m = copy.copy(matcher)
1127
1132
1128 # The m._files and m._map attributes are not changed to the deleted list
1133 # The m._files and m._map attributes are not changed to the deleted list
1129 # because that affects the m.exact() test, which in turn governs whether
1134 # because that affects the m.exact() test, which in turn governs whether
1130 # or not the file name is printed, and how. Simply limit the original
1135 # or not the file name is printed, and how. Simply limit the original
1131 # matches to those in the deleted status list.
1136 # matches to those in the deleted status list.
1132 matchfn = m.matchfn
1137 matchfn = m.matchfn
1133 m.matchfn = lambda f: f in s.deleted and matchfn(f)
1138 m.matchfn = lambda f: f in s.deleted and matchfn(f)
1134
1139
1135 removelargefiles(repo.ui, repo, True, m, **opts)
1140 removelargefiles(repo.ui, repo, True, m, **opts)
1136 # Call into the normal add code, and any files that *should* be added as
1141 # Call into the normal add code, and any files that *should* be added as
1137 # largefiles will be
1142 # largefiles will be
1138 added, bad = addlargefiles(repo.ui, repo, True, matcher, **opts)
1143 added, bad = addlargefiles(repo.ui, repo, True, matcher, **opts)
1139 # Now that we've handled largefiles, hand off to the original addremove
1144 # Now that we've handled largefiles, hand off to the original addremove
1140 # function to take care of the rest. Make sure it doesn't do anything with
1145 # function to take care of the rest. Make sure it doesn't do anything with
1141 # largefiles by passing a matcher that will ignore them.
1146 # largefiles by passing a matcher that will ignore them.
1142 matcher = composenormalfilematcher(matcher, repo[None].manifest(), added)
1147 matcher = composenormalfilematcher(matcher, repo[None].manifest(), added)
1143 return orig(repo, matcher, prefix, opts, dry_run, similarity)
1148 return orig(repo, matcher, prefix, opts, dry_run, similarity)
1144
1149
1145 # Calling purge with --all will cause the largefiles to be deleted.
1150 # Calling purge with --all will cause the largefiles to be deleted.
1146 # Override repo.status to prevent this from happening.
1151 # Override repo.status to prevent this from happening.
1147 def overridepurge(orig, ui, repo, *dirs, **opts):
1152 def overridepurge(orig, ui, repo, *dirs, **opts):
1148 # XXX Monkey patching a repoview will not work. The assigned attribute will
1153 # XXX Monkey patching a repoview will not work. The assigned attribute will
1149 # be set on the unfiltered repo, but we will only lookup attributes in the
1154 # be set on the unfiltered repo, but we will only lookup attributes in the
1150 # unfiltered repo if the lookup in the repoview object itself fails. As the
1155 # unfiltered repo if the lookup in the repoview object itself fails. As the
1151 # monkey patched method exists on the repoview class the lookup will not
1156 # monkey patched method exists on the repoview class the lookup will not
1152 # fail. As a result, the original version will shadow the monkey patched
1157 # fail. As a result, the original version will shadow the monkey patched
1153 # one, defeating the monkey patch.
1158 # one, defeating the monkey patch.
1154 #
1159 #
1155 # As a work around we use an unfiltered repo here. We should do something
1160 # As a work around we use an unfiltered repo here. We should do something
1156 # cleaner instead.
1161 # cleaner instead.
1157 repo = repo.unfiltered()
1162 repo = repo.unfiltered()
1158 oldstatus = repo.status
1163 oldstatus = repo.status
1159 def overridestatus(node1='.', node2=None, match=None, ignored=False,
1164 def overridestatus(node1='.', node2=None, match=None, ignored=False,
1160 clean=False, unknown=False, listsubrepos=False):
1165 clean=False, unknown=False, listsubrepos=False):
1161 r = oldstatus(node1, node2, match, ignored, clean, unknown,
1166 r = oldstatus(node1, node2, match, ignored, clean, unknown,
1162 listsubrepos)
1167 listsubrepos)
1163 lfdirstate = lfutil.openlfdirstate(ui, repo)
1168 lfdirstate = lfutil.openlfdirstate(ui, repo)
1164 unknown = [f for f in r.unknown if lfdirstate[f] == '?']
1169 unknown = [f for f in r.unknown if lfdirstate[f] == '?']
1165 ignored = [f for f in r.ignored if lfdirstate[f] == '?']
1170 ignored = [f for f in r.ignored if lfdirstate[f] == '?']
1166 return scmutil.status(r.modified, r.added, r.removed, r.deleted,
1171 return scmutil.status(r.modified, r.added, r.removed, r.deleted,
1167 unknown, ignored, r.clean)
1172 unknown, ignored, r.clean)
1168 repo.status = overridestatus
1173 repo.status = overridestatus
1169 orig(ui, repo, *dirs, **opts)
1174 orig(ui, repo, *dirs, **opts)
1170 repo.status = oldstatus
1175 repo.status = oldstatus
1171 def overriderollback(orig, ui, repo, **opts):
1176 def overriderollback(orig, ui, repo, **opts):
1172 wlock = repo.wlock()
1177 wlock = repo.wlock()
1173 try:
1178 try:
1174 before = repo.dirstate.parents()
1179 before = repo.dirstate.parents()
1175 orphans = set(f for f in repo.dirstate
1180 orphans = set(f for f in repo.dirstate
1176 if lfutil.isstandin(f) and repo.dirstate[f] != 'r')
1181 if lfutil.isstandin(f) and repo.dirstate[f] != 'r')
1177 result = orig(ui, repo, **opts)
1182 result = orig(ui, repo, **opts)
1178 after = repo.dirstate.parents()
1183 after = repo.dirstate.parents()
1179 if before == after:
1184 if before == after:
1180 return result # no need to restore standins
1185 return result # no need to restore standins
1181
1186
1182 pctx = repo['.']
1187 pctx = repo['.']
1183 for f in repo.dirstate:
1188 for f in repo.dirstate:
1184 if lfutil.isstandin(f):
1189 if lfutil.isstandin(f):
1185 orphans.discard(f)
1190 orphans.discard(f)
1186 if repo.dirstate[f] == 'r':
1191 if repo.dirstate[f] == 'r':
1187 repo.wvfs.unlinkpath(f, ignoremissing=True)
1192 repo.wvfs.unlinkpath(f, ignoremissing=True)
1188 elif f in pctx:
1193 elif f in pctx:
1189 fctx = pctx[f]
1194 fctx = pctx[f]
1190 repo.wwrite(f, fctx.data(), fctx.flags())
1195 repo.wwrite(f, fctx.data(), fctx.flags())
1191 else:
1196 else:
1192 # content of standin is not so important in 'a',
1197 # content of standin is not so important in 'a',
1193 # 'm' or 'n' (coming from the 2nd parent) cases
1198 # 'm' or 'n' (coming from the 2nd parent) cases
1194 lfutil.writestandin(repo, f, '', False)
1199 lfutil.writestandin(repo, f, '', False)
1195 for standin in orphans:
1200 for standin in orphans:
1196 repo.wvfs.unlinkpath(standin, ignoremissing=True)
1201 repo.wvfs.unlinkpath(standin, ignoremissing=True)
1197
1202
1198 lfdirstate = lfutil.openlfdirstate(ui, repo)
1203 lfdirstate = lfutil.openlfdirstate(ui, repo)
1199 orphans = set(lfdirstate)
1204 orphans = set(lfdirstate)
1200 lfiles = lfutil.listlfiles(repo)
1205 lfiles = lfutil.listlfiles(repo)
1201 for file in lfiles:
1206 for file in lfiles:
1202 lfutil.synclfdirstate(repo, lfdirstate, file, True)
1207 lfutil.synclfdirstate(repo, lfdirstate, file, True)
1203 orphans.discard(file)
1208 orphans.discard(file)
1204 for lfile in orphans:
1209 for lfile in orphans:
1205 lfdirstate.drop(lfile)
1210 lfdirstate.drop(lfile)
1206 lfdirstate.write()
1211 lfdirstate.write()
1207 finally:
1212 finally:
1208 wlock.release()
1213 wlock.release()
1209 return result
1214 return result
1210
1215
1211 def overridetransplant(orig, ui, repo, *revs, **opts):
1216 def overridetransplant(orig, ui, repo, *revs, **opts):
1212 resuming = opts.get('continue')
1217 resuming = opts.get('continue')
1213 repo._lfcommithooks.append(lfutil.automatedcommithook(resuming))
1218 repo._lfcommithooks.append(lfutil.automatedcommithook(resuming))
1214 repo._lfstatuswriters.append(lambda *msg, **opts: None)
1219 repo._lfstatuswriters.append(lambda *msg, **opts: None)
1215 try:
1220 try:
1216 result = orig(ui, repo, *revs, **opts)
1221 result = orig(ui, repo, *revs, **opts)
1217 finally:
1222 finally:
1218 repo._lfstatuswriters.pop()
1223 repo._lfstatuswriters.pop()
1219 repo._lfcommithooks.pop()
1224 repo._lfcommithooks.pop()
1220 return result
1225 return result
1221
1226
1222 def overridecat(orig, ui, repo, file1, *pats, **opts):
1227 def overridecat(orig, ui, repo, file1, *pats, **opts):
1223 ctx = scmutil.revsingle(repo, opts.get('rev'))
1228 ctx = scmutil.revsingle(repo, opts.get('rev'))
1224 err = 1
1229 err = 1
1225 notbad = set()
1230 notbad = set()
1226 m = scmutil.match(ctx, (file1,) + pats, opts)
1231 m = scmutil.match(ctx, (file1,) + pats, opts)
1227 origmatchfn = m.matchfn
1232 origmatchfn = m.matchfn
1228 def lfmatchfn(f):
1233 def lfmatchfn(f):
1229 if origmatchfn(f):
1234 if origmatchfn(f):
1230 return True
1235 return True
1231 lf = lfutil.splitstandin(f)
1236 lf = lfutil.splitstandin(f)
1232 if lf is None:
1237 if lf is None:
1233 return False
1238 return False
1234 notbad.add(lf)
1239 notbad.add(lf)
1235 return origmatchfn(lf)
1240 return origmatchfn(lf)
1236 m.matchfn = lfmatchfn
1241 m.matchfn = lfmatchfn
1237 origbadfn = m.bad
1242 origbadfn = m.bad
1238 def lfbadfn(f, msg):
1243 def lfbadfn(f, msg):
1239 if not f in notbad:
1244 if not f in notbad:
1240 origbadfn(f, msg)
1245 origbadfn(f, msg)
1241 m.bad = lfbadfn
1246 m.bad = lfbadfn
1242 for f in ctx.walk(m):
1247 for f in ctx.walk(m):
1243 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1248 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1244 pathname=f)
1249 pathname=f)
1245 lf = lfutil.splitstandin(f)
1250 lf = lfutil.splitstandin(f)
1246 if lf is None or origmatchfn(f):
1251 if lf is None or origmatchfn(f):
1247 # duplicating unreachable code from commands.cat
1252 # duplicating unreachable code from commands.cat
1248 data = ctx[f].data()
1253 data = ctx[f].data()
1249 if opts.get('decode'):
1254 if opts.get('decode'):
1250 data = repo.wwritedata(f, data)
1255 data = repo.wwritedata(f, data)
1251 fp.write(data)
1256 fp.write(data)
1252 else:
1257 else:
1253 hash = lfutil.readstandin(repo, lf, ctx.rev())
1258 hash = lfutil.readstandin(repo, lf, ctx.rev())
1254 if not lfutil.inusercache(repo.ui, hash):
1259 if not lfutil.inusercache(repo.ui, hash):
1255 store = basestore._openstore(repo)
1260 store = basestore._openstore(repo)
1256 success, missing = store.get([(lf, hash)])
1261 success, missing = store.get([(lf, hash)])
1257 if len(success) != 1:
1262 if len(success) != 1:
1258 raise util.Abort(
1263 raise util.Abort(
1259 _('largefile %s is not in cache and could not be '
1264 _('largefile %s is not in cache and could not be '
1260 'downloaded') % lf)
1265 'downloaded') % lf)
1261 path = lfutil.usercachepath(repo.ui, hash)
1266 path = lfutil.usercachepath(repo.ui, hash)
1262 fpin = open(path, "rb")
1267 fpin = open(path, "rb")
1263 for chunk in util.filechunkiter(fpin, 128 * 1024):
1268 for chunk in util.filechunkiter(fpin, 128 * 1024):
1264 fp.write(chunk)
1269 fp.write(chunk)
1265 fpin.close()
1270 fpin.close()
1266 fp.close()
1271 fp.close()
1267 err = 0
1272 err = 0
1268 return err
1273 return err
1269
1274
1270 def mergeupdate(orig, repo, node, branchmerge, force, partial,
1275 def mergeupdate(orig, repo, node, branchmerge, force, partial,
1271 *args, **kwargs):
1276 *args, **kwargs):
1272 wlock = repo.wlock()
1277 wlock = repo.wlock()
1273 try:
1278 try:
1274 # branch | | |
1279 # branch | | |
1275 # merge | force | partial | action
1280 # merge | force | partial | action
1276 # -------+-------+---------+--------------
1281 # -------+-------+---------+--------------
1277 # x | x | x | linear-merge
1282 # x | x | x | linear-merge
1278 # o | x | x | branch-merge
1283 # o | x | x | branch-merge
1279 # x | o | x | overwrite (as clean update)
1284 # x | o | x | overwrite (as clean update)
1280 # o | o | x | force-branch-merge (*1)
1285 # o | o | x | force-branch-merge (*1)
1281 # x | x | o | (*)
1286 # x | x | o | (*)
1282 # o | x | o | (*)
1287 # o | x | o | (*)
1283 # x | o | o | overwrite (as revert)
1288 # x | o | o | overwrite (as revert)
1284 # o | o | o | (*)
1289 # o | o | o | (*)
1285 #
1290 #
1286 # (*) don't care
1291 # (*) don't care
1287 # (*1) deprecated, but used internally (e.g: "rebase --collapse")
1292 # (*1) deprecated, but used internally (e.g: "rebase --collapse")
1288
1293
1289 linearmerge = not branchmerge and not force and not partial
1294 linearmerge = not branchmerge and not force and not partial
1290
1295
1291 if linearmerge or (branchmerge and force and not partial):
1296 if linearmerge or (branchmerge and force and not partial):
1292 # update standins for linear-merge or force-branch-merge,
1297 # update standins for linear-merge or force-branch-merge,
1293 # because largefiles in the working directory may be modified
1298 # because largefiles in the working directory may be modified
1294 lfdirstate = lfutil.openlfdirstate(repo.ui, repo)
1299 lfdirstate = lfutil.openlfdirstate(repo.ui, repo)
1295 unsure, s = lfdirstate.status(match_.always(repo.root,
1300 unsure, s = lfdirstate.status(match_.always(repo.root,
1296 repo.getcwd()),
1301 repo.getcwd()),
1297 [], False, False, False)
1302 [], False, False, False)
1298 pctx = repo['.']
1303 pctx = repo['.']
1299 for lfile in unsure + s.modified:
1304 for lfile in unsure + s.modified:
1300 lfileabs = repo.wvfs.join(lfile)
1305 lfileabs = repo.wvfs.join(lfile)
1301 if not os.path.exists(lfileabs):
1306 if not os.path.exists(lfileabs):
1302 continue
1307 continue
1303 lfhash = lfutil.hashrepofile(repo, lfile)
1308 lfhash = lfutil.hashrepofile(repo, lfile)
1304 standin = lfutil.standin(lfile)
1309 standin = lfutil.standin(lfile)
1305 lfutil.writestandin(repo, standin, lfhash,
1310 lfutil.writestandin(repo, standin, lfhash,
1306 lfutil.getexecutable(lfileabs))
1311 lfutil.getexecutable(lfileabs))
1307 if (standin in pctx and
1312 if (standin in pctx and
1308 lfhash == lfutil.readstandin(repo, lfile, '.')):
1313 lfhash == lfutil.readstandin(repo, lfile, '.')):
1309 lfdirstate.normal(lfile)
1314 lfdirstate.normal(lfile)
1310 for lfile in s.added:
1315 for lfile in s.added:
1311 lfutil.updatestandin(repo, lfutil.standin(lfile))
1316 lfutil.updatestandin(repo, lfutil.standin(lfile))
1312 lfdirstate.write()
1317 lfdirstate.write()
1313
1318
1314 if linearmerge:
1319 if linearmerge:
1315 # Only call updatelfiles on the standins that have changed
1320 # Only call updatelfiles on the standins that have changed
1316 # to save time
1321 # to save time
1317 oldstandins = lfutil.getstandinsstate(repo)
1322 oldstandins = lfutil.getstandinsstate(repo)
1318
1323
1319 result = orig(repo, node, branchmerge, force, partial, *args, **kwargs)
1324 result = orig(repo, node, branchmerge, force, partial, *args, **kwargs)
1320
1325
1321 filelist = None
1326 filelist = None
1322 if linearmerge:
1327 if linearmerge:
1323 newstandins = lfutil.getstandinsstate(repo)
1328 newstandins = lfutil.getstandinsstate(repo)
1324 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
1329 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
1325
1330
1326 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist,
1331 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist,
1327 normallookup=partial, checked=linearmerge)
1332 normallookup=partial, checked=linearmerge)
1328
1333
1329 return result
1334 return result
1330 finally:
1335 finally:
1331 wlock.release()
1336 wlock.release()
1332
1337
1333 def scmutilmarktouched(orig, repo, files, *args, **kwargs):
1338 def scmutilmarktouched(orig, repo, files, *args, **kwargs):
1334 result = orig(repo, files, *args, **kwargs)
1339 result = orig(repo, files, *args, **kwargs)
1335
1340
1336 filelist = [lfutil.splitstandin(f) for f in files if lfutil.isstandin(f)]
1341 filelist = [lfutil.splitstandin(f) for f in files if lfutil.isstandin(f)]
1337 if filelist:
1342 if filelist:
1338 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist,
1343 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist,
1339 printmessage=False, normallookup=True)
1344 printmessage=False, normallookup=True)
1340
1345
1341 return result
1346 return result
@@ -1,1932 +1,1945 b''
1 Log on empty repository: checking consistency
1 Log on empty repository: checking consistency
2
2
3 $ hg init empty
3 $ hg init empty
4 $ cd empty
4 $ cd empty
5 $ hg log
5 $ hg log
6 $ hg log -r 1
6 $ hg log -r 1
7 abort: unknown revision '1'!
7 abort: unknown revision '1'!
8 [255]
8 [255]
9 $ hg log -r -1:0
9 $ hg log -r -1:0
10 abort: unknown revision '-1'!
10 abort: unknown revision '-1'!
11 [255]
11 [255]
12 $ hg log -r 'branch(name)'
12 $ hg log -r 'branch(name)'
13 abort: unknown revision 'name'!
13 abort: unknown revision 'name'!
14 [255]
14 [255]
15 $ hg log -r null -q
15 $ hg log -r null -q
16 -1:000000000000
16 -1:000000000000
17
17
18 The g is crafted to have 2 filelog topological heads in a linear
18 The g is crafted to have 2 filelog topological heads in a linear
19 changeset graph
19 changeset graph
20
20
21 $ hg init a
21 $ hg init a
22 $ cd a
22 $ cd a
23 $ echo a > a
23 $ echo a > a
24 $ echo f > f
24 $ echo f > f
25 $ hg ci -Ama -d '1 0'
25 $ hg ci -Ama -d '1 0'
26 adding a
26 adding a
27 adding f
27 adding f
28
28
29 $ hg cp a b
29 $ hg cp a b
30 $ hg cp f g
30 $ hg cp f g
31 $ hg ci -mb -d '2 0'
31 $ hg ci -mb -d '2 0'
32
32
33 $ mkdir dir
33 $ mkdir dir
34 $ hg mv b dir
34 $ hg mv b dir
35 $ echo g >> g
35 $ echo g >> g
36 $ echo f >> f
36 $ echo f >> f
37 $ hg ci -mc -d '3 0'
37 $ hg ci -mc -d '3 0'
38
38
39 $ hg mv a b
39 $ hg mv a b
40 $ hg cp -f f g
40 $ hg cp -f f g
41 $ echo a > d
41 $ echo a > d
42 $ hg add d
42 $ hg add d
43 $ hg ci -md -d '4 0'
43 $ hg ci -md -d '4 0'
44
44
45 $ hg mv dir/b e
45 $ hg mv dir/b e
46 $ hg ci -me -d '5 0'
46 $ hg ci -me -d '5 0'
47
47
48 Make sure largefiles doesn't interfere with logging a regular file
49 $ hg log a --config extensions.largefiles=
50 changeset: 0:9161b9aeaf16
51 user: test
52 date: Thu Jan 01 00:00:01 1970 +0000
53 summary: a
54
48 $ hg log a
55 $ hg log a
49 changeset: 0:9161b9aeaf16
56 changeset: 0:9161b9aeaf16
50 user: test
57 user: test
51 date: Thu Jan 01 00:00:01 1970 +0000
58 date: Thu Jan 01 00:00:01 1970 +0000
52 summary: a
59 summary: a
53
60
54 log on directory
61 log on directory
55
62
56 $ hg log dir
63 $ hg log dir
57 changeset: 4:7e4639b4691b
64 changeset: 4:7e4639b4691b
58 tag: tip
65 tag: tip
59 user: test
66 user: test
60 date: Thu Jan 01 00:00:05 1970 +0000
67 date: Thu Jan 01 00:00:05 1970 +0000
61 summary: e
68 summary: e
62
69
63 changeset: 2:f8954cd4dc1f
70 changeset: 2:f8954cd4dc1f
64 user: test
71 user: test
65 date: Thu Jan 01 00:00:03 1970 +0000
72 date: Thu Jan 01 00:00:03 1970 +0000
66 summary: c
73 summary: c
67
74
68 $ hg log somethingthatdoesntexist dir
75 $ hg log somethingthatdoesntexist dir
69 changeset: 4:7e4639b4691b
76 changeset: 4:7e4639b4691b
70 tag: tip
77 tag: tip
71 user: test
78 user: test
72 date: Thu Jan 01 00:00:05 1970 +0000
79 date: Thu Jan 01 00:00:05 1970 +0000
73 summary: e
80 summary: e
74
81
75 changeset: 2:f8954cd4dc1f
82 changeset: 2:f8954cd4dc1f
76 user: test
83 user: test
77 date: Thu Jan 01 00:00:03 1970 +0000
84 date: Thu Jan 01 00:00:03 1970 +0000
78 summary: c
85 summary: c
79
86
80
87
81 -f, non-existent directory
88 -f, non-existent directory
82
89
83 $ hg log -f dir
90 $ hg log -f dir
84 abort: cannot follow file not in parent revision: "dir"
91 abort: cannot follow file not in parent revision: "dir"
85 [255]
92 [255]
86
93
87 -f, directory
94 -f, directory
88
95
89 $ hg up -q 3
96 $ hg up -q 3
90 $ hg log -f dir
97 $ hg log -f dir
91 changeset: 2:f8954cd4dc1f
98 changeset: 2:f8954cd4dc1f
92 user: test
99 user: test
93 date: Thu Jan 01 00:00:03 1970 +0000
100 date: Thu Jan 01 00:00:03 1970 +0000
94 summary: c
101 summary: c
95
102
96 -f, directory with --patch
103 -f, directory with --patch
97
104
98 $ hg log -f dir -p
105 $ hg log -f dir -p
99 changeset: 2:f8954cd4dc1f
106 changeset: 2:f8954cd4dc1f
100 user: test
107 user: test
101 date: Thu Jan 01 00:00:03 1970 +0000
108 date: Thu Jan 01 00:00:03 1970 +0000
102 summary: c
109 summary: c
103
110
104 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
111 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
105 --- /dev/null* (glob)
112 --- /dev/null* (glob)
106 +++ b/dir/b* (glob)
113 +++ b/dir/b* (glob)
107 @@ -0,0 +1,1 @@
114 @@ -0,0 +1,1 @@
108 +a
115 +a
109
116
110
117
111 -f, pattern
118 -f, pattern
112
119
113 $ hg log -f -I 'dir**' -p
120 $ hg log -f -I 'dir**' -p
114 changeset: 2:f8954cd4dc1f
121 changeset: 2:f8954cd4dc1f
115 user: test
122 user: test
116 date: Thu Jan 01 00:00:03 1970 +0000
123 date: Thu Jan 01 00:00:03 1970 +0000
117 summary: c
124 summary: c
118
125
119 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
126 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
120 --- /dev/null* (glob)
127 --- /dev/null* (glob)
121 +++ b/dir/b* (glob)
128 +++ b/dir/b* (glob)
122 @@ -0,0 +1,1 @@
129 @@ -0,0 +1,1 @@
123 +a
130 +a
124
131
125 $ hg up -q 4
132 $ hg up -q 4
126
133
127 -f, a wrong style
134 -f, a wrong style
128
135
129 $ hg log -f -l1 --style something
136 $ hg log -f -l1 --style something
130 abort: style 'something' not found
137 abort: style 'something' not found
131 (available styles: bisect, changelog, compact, default, phases, xml)
138 (available styles: bisect, changelog, compact, default, phases, xml)
132 [255]
139 [255]
133
140
134 -f, phases style
141 -f, phases style
135
142
136
143
137 $ hg log -f -l1 --style phases
144 $ hg log -f -l1 --style phases
138 changeset: 4:7e4639b4691b
145 changeset: 4:7e4639b4691b
139 tag: tip
146 tag: tip
140 phase: draft
147 phase: draft
141 user: test
148 user: test
142 date: Thu Jan 01 00:00:05 1970 +0000
149 date: Thu Jan 01 00:00:05 1970 +0000
143 summary: e
150 summary: e
144
151
145
152
146 -f, but no args
153 -f, but no args
147
154
148 $ hg log -f
155 $ hg log -f
149 changeset: 4:7e4639b4691b
156 changeset: 4:7e4639b4691b
150 tag: tip
157 tag: tip
151 user: test
158 user: test
152 date: Thu Jan 01 00:00:05 1970 +0000
159 date: Thu Jan 01 00:00:05 1970 +0000
153 summary: e
160 summary: e
154
161
155 changeset: 3:2ca5ba701980
162 changeset: 3:2ca5ba701980
156 user: test
163 user: test
157 date: Thu Jan 01 00:00:04 1970 +0000
164 date: Thu Jan 01 00:00:04 1970 +0000
158 summary: d
165 summary: d
159
166
160 changeset: 2:f8954cd4dc1f
167 changeset: 2:f8954cd4dc1f
161 user: test
168 user: test
162 date: Thu Jan 01 00:00:03 1970 +0000
169 date: Thu Jan 01 00:00:03 1970 +0000
163 summary: c
170 summary: c
164
171
165 changeset: 1:d89b0a12d229
172 changeset: 1:d89b0a12d229
166 user: test
173 user: test
167 date: Thu Jan 01 00:00:02 1970 +0000
174 date: Thu Jan 01 00:00:02 1970 +0000
168 summary: b
175 summary: b
169
176
170 changeset: 0:9161b9aeaf16
177 changeset: 0:9161b9aeaf16
171 user: test
178 user: test
172 date: Thu Jan 01 00:00:01 1970 +0000
179 date: Thu Jan 01 00:00:01 1970 +0000
173 summary: a
180 summary: a
174
181
175
182
176 one rename
183 one rename
177
184
178 $ hg up -q 2
185 $ hg up -q 2
179 $ hg log -vf a
186 $ hg log -vf a
180 changeset: 0:9161b9aeaf16
187 changeset: 0:9161b9aeaf16
181 user: test
188 user: test
182 date: Thu Jan 01 00:00:01 1970 +0000
189 date: Thu Jan 01 00:00:01 1970 +0000
183 files: a f
190 files: a f
184 description:
191 description:
185 a
192 a
186
193
187
194
188
195
189 many renames
196 many renames
190
197
191 $ hg up -q tip
198 $ hg up -q tip
192 $ hg log -vf e
199 $ hg log -vf e
193 changeset: 4:7e4639b4691b
200 changeset: 4:7e4639b4691b
194 tag: tip
201 tag: tip
195 user: test
202 user: test
196 date: Thu Jan 01 00:00:05 1970 +0000
203 date: Thu Jan 01 00:00:05 1970 +0000
197 files: dir/b e
204 files: dir/b e
198 description:
205 description:
199 e
206 e
200
207
201
208
202 changeset: 2:f8954cd4dc1f
209 changeset: 2:f8954cd4dc1f
203 user: test
210 user: test
204 date: Thu Jan 01 00:00:03 1970 +0000
211 date: Thu Jan 01 00:00:03 1970 +0000
205 files: b dir/b f g
212 files: b dir/b f g
206 description:
213 description:
207 c
214 c
208
215
209
216
210 changeset: 1:d89b0a12d229
217 changeset: 1:d89b0a12d229
211 user: test
218 user: test
212 date: Thu Jan 01 00:00:02 1970 +0000
219 date: Thu Jan 01 00:00:02 1970 +0000
213 files: b g
220 files: b g
214 description:
221 description:
215 b
222 b
216
223
217
224
218 changeset: 0:9161b9aeaf16
225 changeset: 0:9161b9aeaf16
219 user: test
226 user: test
220 date: Thu Jan 01 00:00:01 1970 +0000
227 date: Thu Jan 01 00:00:01 1970 +0000
221 files: a f
228 files: a f
222 description:
229 description:
223 a
230 a
224
231
225
232
226
233
227
234
228 log -pf dir/b
235 log -pf dir/b
229
236
230 $ hg up -q 3
237 $ hg up -q 3
231 $ hg log -pf dir/b
238 $ hg log -pf dir/b
232 changeset: 2:f8954cd4dc1f
239 changeset: 2:f8954cd4dc1f
233 user: test
240 user: test
234 date: Thu Jan 01 00:00:03 1970 +0000
241 date: Thu Jan 01 00:00:03 1970 +0000
235 summary: c
242 summary: c
236
243
237 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
244 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
238 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
245 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
239 +++ b/dir/b Thu Jan 01 00:00:03 1970 +0000
246 +++ b/dir/b Thu Jan 01 00:00:03 1970 +0000
240 @@ -0,0 +1,1 @@
247 @@ -0,0 +1,1 @@
241 +a
248 +a
242
249
243 changeset: 1:d89b0a12d229
250 changeset: 1:d89b0a12d229
244 user: test
251 user: test
245 date: Thu Jan 01 00:00:02 1970 +0000
252 date: Thu Jan 01 00:00:02 1970 +0000
246 summary: b
253 summary: b
247
254
248 diff -r 9161b9aeaf16 -r d89b0a12d229 b
255 diff -r 9161b9aeaf16 -r d89b0a12d229 b
249 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
256 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
250 +++ b/b Thu Jan 01 00:00:02 1970 +0000
257 +++ b/b Thu Jan 01 00:00:02 1970 +0000
251 @@ -0,0 +1,1 @@
258 @@ -0,0 +1,1 @@
252 +a
259 +a
253
260
254 changeset: 0:9161b9aeaf16
261 changeset: 0:9161b9aeaf16
255 user: test
262 user: test
256 date: Thu Jan 01 00:00:01 1970 +0000
263 date: Thu Jan 01 00:00:01 1970 +0000
257 summary: a
264 summary: a
258
265
259 diff -r 000000000000 -r 9161b9aeaf16 a
266 diff -r 000000000000 -r 9161b9aeaf16 a
260 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
267 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
261 +++ b/a Thu Jan 01 00:00:01 1970 +0000
268 +++ b/a Thu Jan 01 00:00:01 1970 +0000
262 @@ -0,0 +1,1 @@
269 @@ -0,0 +1,1 @@
263 +a
270 +a
264
271
265
272
266 log -pf b inside dir
273 log -pf b inside dir
267
274
268 $ hg --cwd=dir log -pf b
275 $ hg --cwd=dir log -pf b
269 changeset: 2:f8954cd4dc1f
276 changeset: 2:f8954cd4dc1f
270 user: test
277 user: test
271 date: Thu Jan 01 00:00:03 1970 +0000
278 date: Thu Jan 01 00:00:03 1970 +0000
272 summary: c
279 summary: c
273
280
274 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
281 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
275 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
282 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
276 +++ b/dir/b Thu Jan 01 00:00:03 1970 +0000
283 +++ b/dir/b Thu Jan 01 00:00:03 1970 +0000
277 @@ -0,0 +1,1 @@
284 @@ -0,0 +1,1 @@
278 +a
285 +a
279
286
280 changeset: 1:d89b0a12d229
287 changeset: 1:d89b0a12d229
281 user: test
288 user: test
282 date: Thu Jan 01 00:00:02 1970 +0000
289 date: Thu Jan 01 00:00:02 1970 +0000
283 summary: b
290 summary: b
284
291
285 diff -r 9161b9aeaf16 -r d89b0a12d229 b
292 diff -r 9161b9aeaf16 -r d89b0a12d229 b
286 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
293 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
287 +++ b/b Thu Jan 01 00:00:02 1970 +0000
294 +++ b/b Thu Jan 01 00:00:02 1970 +0000
288 @@ -0,0 +1,1 @@
295 @@ -0,0 +1,1 @@
289 +a
296 +a
290
297
291 changeset: 0:9161b9aeaf16
298 changeset: 0:9161b9aeaf16
292 user: test
299 user: test
293 date: Thu Jan 01 00:00:01 1970 +0000
300 date: Thu Jan 01 00:00:01 1970 +0000
294 summary: a
301 summary: a
295
302
296 diff -r 000000000000 -r 9161b9aeaf16 a
303 diff -r 000000000000 -r 9161b9aeaf16 a
297 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
304 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
298 +++ b/a Thu Jan 01 00:00:01 1970 +0000
305 +++ b/a Thu Jan 01 00:00:01 1970 +0000
299 @@ -0,0 +1,1 @@
306 @@ -0,0 +1,1 @@
300 +a
307 +a
301
308
302
309
303 log -pf, but no args
310 log -pf, but no args
304
311
305 $ hg log -pf
312 $ hg log -pf
306 changeset: 3:2ca5ba701980
313 changeset: 3:2ca5ba701980
307 user: test
314 user: test
308 date: Thu Jan 01 00:00:04 1970 +0000
315 date: Thu Jan 01 00:00:04 1970 +0000
309 summary: d
316 summary: d
310
317
311 diff -r f8954cd4dc1f -r 2ca5ba701980 a
318 diff -r f8954cd4dc1f -r 2ca5ba701980 a
312 --- a/a Thu Jan 01 00:00:03 1970 +0000
319 --- a/a Thu Jan 01 00:00:03 1970 +0000
313 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
320 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
314 @@ -1,1 +0,0 @@
321 @@ -1,1 +0,0 @@
315 -a
322 -a
316 diff -r f8954cd4dc1f -r 2ca5ba701980 b
323 diff -r f8954cd4dc1f -r 2ca5ba701980 b
317 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
324 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
318 +++ b/b Thu Jan 01 00:00:04 1970 +0000
325 +++ b/b Thu Jan 01 00:00:04 1970 +0000
319 @@ -0,0 +1,1 @@
326 @@ -0,0 +1,1 @@
320 +a
327 +a
321 diff -r f8954cd4dc1f -r 2ca5ba701980 d
328 diff -r f8954cd4dc1f -r 2ca5ba701980 d
322 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
329 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
323 +++ b/d Thu Jan 01 00:00:04 1970 +0000
330 +++ b/d Thu Jan 01 00:00:04 1970 +0000
324 @@ -0,0 +1,1 @@
331 @@ -0,0 +1,1 @@
325 +a
332 +a
326 diff -r f8954cd4dc1f -r 2ca5ba701980 g
333 diff -r f8954cd4dc1f -r 2ca5ba701980 g
327 --- a/g Thu Jan 01 00:00:03 1970 +0000
334 --- a/g Thu Jan 01 00:00:03 1970 +0000
328 +++ b/g Thu Jan 01 00:00:04 1970 +0000
335 +++ b/g Thu Jan 01 00:00:04 1970 +0000
329 @@ -1,2 +1,2 @@
336 @@ -1,2 +1,2 @@
330 f
337 f
331 -g
338 -g
332 +f
339 +f
333
340
334 changeset: 2:f8954cd4dc1f
341 changeset: 2:f8954cd4dc1f
335 user: test
342 user: test
336 date: Thu Jan 01 00:00:03 1970 +0000
343 date: Thu Jan 01 00:00:03 1970 +0000
337 summary: c
344 summary: c
338
345
339 diff -r d89b0a12d229 -r f8954cd4dc1f b
346 diff -r d89b0a12d229 -r f8954cd4dc1f b
340 --- a/b Thu Jan 01 00:00:02 1970 +0000
347 --- a/b Thu Jan 01 00:00:02 1970 +0000
341 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
348 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
342 @@ -1,1 +0,0 @@
349 @@ -1,1 +0,0 @@
343 -a
350 -a
344 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
351 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
345 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
352 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
346 +++ b/dir/b Thu Jan 01 00:00:03 1970 +0000
353 +++ b/dir/b Thu Jan 01 00:00:03 1970 +0000
347 @@ -0,0 +1,1 @@
354 @@ -0,0 +1,1 @@
348 +a
355 +a
349 diff -r d89b0a12d229 -r f8954cd4dc1f f
356 diff -r d89b0a12d229 -r f8954cd4dc1f f
350 --- a/f Thu Jan 01 00:00:02 1970 +0000
357 --- a/f Thu Jan 01 00:00:02 1970 +0000
351 +++ b/f Thu Jan 01 00:00:03 1970 +0000
358 +++ b/f Thu Jan 01 00:00:03 1970 +0000
352 @@ -1,1 +1,2 @@
359 @@ -1,1 +1,2 @@
353 f
360 f
354 +f
361 +f
355 diff -r d89b0a12d229 -r f8954cd4dc1f g
362 diff -r d89b0a12d229 -r f8954cd4dc1f g
356 --- a/g Thu Jan 01 00:00:02 1970 +0000
363 --- a/g Thu Jan 01 00:00:02 1970 +0000
357 +++ b/g Thu Jan 01 00:00:03 1970 +0000
364 +++ b/g Thu Jan 01 00:00:03 1970 +0000
358 @@ -1,1 +1,2 @@
365 @@ -1,1 +1,2 @@
359 f
366 f
360 +g
367 +g
361
368
362 changeset: 1:d89b0a12d229
369 changeset: 1:d89b0a12d229
363 user: test
370 user: test
364 date: Thu Jan 01 00:00:02 1970 +0000
371 date: Thu Jan 01 00:00:02 1970 +0000
365 summary: b
372 summary: b
366
373
367 diff -r 9161b9aeaf16 -r d89b0a12d229 b
374 diff -r 9161b9aeaf16 -r d89b0a12d229 b
368 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
375 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
369 +++ b/b Thu Jan 01 00:00:02 1970 +0000
376 +++ b/b Thu Jan 01 00:00:02 1970 +0000
370 @@ -0,0 +1,1 @@
377 @@ -0,0 +1,1 @@
371 +a
378 +a
372 diff -r 9161b9aeaf16 -r d89b0a12d229 g
379 diff -r 9161b9aeaf16 -r d89b0a12d229 g
373 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
380 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
374 +++ b/g Thu Jan 01 00:00:02 1970 +0000
381 +++ b/g Thu Jan 01 00:00:02 1970 +0000
375 @@ -0,0 +1,1 @@
382 @@ -0,0 +1,1 @@
376 +f
383 +f
377
384
378 changeset: 0:9161b9aeaf16
385 changeset: 0:9161b9aeaf16
379 user: test
386 user: test
380 date: Thu Jan 01 00:00:01 1970 +0000
387 date: Thu Jan 01 00:00:01 1970 +0000
381 summary: a
388 summary: a
382
389
383 diff -r 000000000000 -r 9161b9aeaf16 a
390 diff -r 000000000000 -r 9161b9aeaf16 a
384 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
391 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
385 +++ b/a Thu Jan 01 00:00:01 1970 +0000
392 +++ b/a Thu Jan 01 00:00:01 1970 +0000
386 @@ -0,0 +1,1 @@
393 @@ -0,0 +1,1 @@
387 +a
394 +a
388 diff -r 000000000000 -r 9161b9aeaf16 f
395 diff -r 000000000000 -r 9161b9aeaf16 f
389 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
396 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
390 +++ b/f Thu Jan 01 00:00:01 1970 +0000
397 +++ b/f Thu Jan 01 00:00:01 1970 +0000
391 @@ -0,0 +1,1 @@
398 @@ -0,0 +1,1 @@
392 +f
399 +f
393
400
394
401
395 log -vf dir/b
402 log -vf dir/b
396
403
397 $ hg log -vf dir/b
404 $ hg log -vf dir/b
398 changeset: 2:f8954cd4dc1f
405 changeset: 2:f8954cd4dc1f
399 user: test
406 user: test
400 date: Thu Jan 01 00:00:03 1970 +0000
407 date: Thu Jan 01 00:00:03 1970 +0000
401 files: b dir/b f g
408 files: b dir/b f g
402 description:
409 description:
403 c
410 c
404
411
405
412
406 changeset: 1:d89b0a12d229
413 changeset: 1:d89b0a12d229
407 user: test
414 user: test
408 date: Thu Jan 01 00:00:02 1970 +0000
415 date: Thu Jan 01 00:00:02 1970 +0000
409 files: b g
416 files: b g
410 description:
417 description:
411 b
418 b
412
419
413
420
414 changeset: 0:9161b9aeaf16
421 changeset: 0:9161b9aeaf16
415 user: test
422 user: test
416 date: Thu Jan 01 00:00:01 1970 +0000
423 date: Thu Jan 01 00:00:01 1970 +0000
417 files: a f
424 files: a f
418 description:
425 description:
419 a
426 a
420
427
421
428
422
429
423
430
424 -f and multiple filelog heads
431 -f and multiple filelog heads
425
432
426 $ hg up -q 2
433 $ hg up -q 2
427 $ hg log -f g --template '{rev}\n'
434 $ hg log -f g --template '{rev}\n'
428 2
435 2
429 1
436 1
430 0
437 0
431 $ hg up -q tip
438 $ hg up -q tip
432 $ hg log -f g --template '{rev}\n'
439 $ hg log -f g --template '{rev}\n'
433 3
440 3
434 2
441 2
435 0
442 0
436
443
437
444
438 log copies with --copies
445 log copies with --copies
439
446
440 $ hg log -vC --template '{rev} {file_copies}\n'
447 $ hg log -vC --template '{rev} {file_copies}\n'
441 4 e (dir/b)
448 4 e (dir/b)
442 3 b (a)g (f)
449 3 b (a)g (f)
443 2 dir/b (b)
450 2 dir/b (b)
444 1 b (a)g (f)
451 1 b (a)g (f)
445 0
452 0
446
453
447 log copies switch without --copies, with old filecopy template
454 log copies switch without --copies, with old filecopy template
448
455
449 $ hg log -v --template '{rev} {file_copies_switch%filecopy}\n'
456 $ hg log -v --template '{rev} {file_copies_switch%filecopy}\n'
450 4
457 4
451 3
458 3
452 2
459 2
453 1
460 1
454 0
461 0
455
462
456 log copies switch with --copies
463 log copies switch with --copies
457
464
458 $ hg log -vC --template '{rev} {file_copies_switch}\n'
465 $ hg log -vC --template '{rev} {file_copies_switch}\n'
459 4 e (dir/b)
466 4 e (dir/b)
460 3 b (a)g (f)
467 3 b (a)g (f)
461 2 dir/b (b)
468 2 dir/b (b)
462 1 b (a)g (f)
469 1 b (a)g (f)
463 0
470 0
464
471
465
472
466 log copies with hardcoded style and with --style=default
473 log copies with hardcoded style and with --style=default
467
474
468 $ hg log -vC -r4
475 $ hg log -vC -r4
469 changeset: 4:7e4639b4691b
476 changeset: 4:7e4639b4691b
470 tag: tip
477 tag: tip
471 user: test
478 user: test
472 date: Thu Jan 01 00:00:05 1970 +0000
479 date: Thu Jan 01 00:00:05 1970 +0000
473 files: dir/b e
480 files: dir/b e
474 copies: e (dir/b)
481 copies: e (dir/b)
475 description:
482 description:
476 e
483 e
477
484
478
485
479 $ hg log -vC -r4 --style=default
486 $ hg log -vC -r4 --style=default
480 changeset: 4:7e4639b4691b
487 changeset: 4:7e4639b4691b
481 tag: tip
488 tag: tip
482 user: test
489 user: test
483 date: Thu Jan 01 00:00:05 1970 +0000
490 date: Thu Jan 01 00:00:05 1970 +0000
484 files: dir/b e
491 files: dir/b e
485 copies: e (dir/b)
492 copies: e (dir/b)
486 description:
493 description:
487 e
494 e
488
495
489
496
490
497
491
498
492 log copies, non-linear manifest
499 log copies, non-linear manifest
493
500
494 $ hg up -C 3
501 $ hg up -C 3
495 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
502 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
496 $ hg mv dir/b e
503 $ hg mv dir/b e
497 $ echo foo > foo
504 $ echo foo > foo
498 $ hg ci -Ame2 -d '6 0'
505 $ hg ci -Ame2 -d '6 0'
499 adding foo
506 adding foo
500 created new head
507 created new head
501 $ hg log -v --template '{rev} {file_copies}\n' -r 5
508 $ hg log -v --template '{rev} {file_copies}\n' -r 5
502 5 e (dir/b)
509 5 e (dir/b)
503
510
504
511
505 log copies, execute bit set
512 log copies, execute bit set
506
513
507 #if execbit
514 #if execbit
508 $ chmod +x e
515 $ chmod +x e
509 $ hg ci -me3 -d '7 0'
516 $ hg ci -me3 -d '7 0'
510 $ hg log -v --template '{rev} {file_copies}\n' -r 6
517 $ hg log -v --template '{rev} {file_copies}\n' -r 6
511 6
518 6
512 #endif
519 #endif
513
520
514
521
515 log -p d
522 log -p d
516
523
517 $ hg log -pv d
524 $ hg log -pv d
518 changeset: 3:2ca5ba701980
525 changeset: 3:2ca5ba701980
519 user: test
526 user: test
520 date: Thu Jan 01 00:00:04 1970 +0000
527 date: Thu Jan 01 00:00:04 1970 +0000
521 files: a b d g
528 files: a b d g
522 description:
529 description:
523 d
530 d
524
531
525
532
526 diff -r f8954cd4dc1f -r 2ca5ba701980 d
533 diff -r f8954cd4dc1f -r 2ca5ba701980 d
527 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
534 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
528 +++ b/d Thu Jan 01 00:00:04 1970 +0000
535 +++ b/d Thu Jan 01 00:00:04 1970 +0000
529 @@ -0,0 +1,1 @@
536 @@ -0,0 +1,1 @@
530 +a
537 +a
531
538
532
539
533
540
534 log --removed file
541 log --removed file
535
542
536 $ hg log --removed -v a
543 $ hg log --removed -v a
537 changeset: 3:2ca5ba701980
544 changeset: 3:2ca5ba701980
538 user: test
545 user: test
539 date: Thu Jan 01 00:00:04 1970 +0000
546 date: Thu Jan 01 00:00:04 1970 +0000
540 files: a b d g
547 files: a b d g
541 description:
548 description:
542 d
549 d
543
550
544
551
545 changeset: 0:9161b9aeaf16
552 changeset: 0:9161b9aeaf16
546 user: test
553 user: test
547 date: Thu Jan 01 00:00:01 1970 +0000
554 date: Thu Jan 01 00:00:01 1970 +0000
548 files: a f
555 files: a f
549 description:
556 description:
550 a
557 a
551
558
552
559
553
560
554 log --removed revrange file
561 log --removed revrange file
555
562
556 $ hg log --removed -v -r0:2 a
563 $ hg log --removed -v -r0:2 a
557 changeset: 0:9161b9aeaf16
564 changeset: 0:9161b9aeaf16
558 user: test
565 user: test
559 date: Thu Jan 01 00:00:01 1970 +0000
566 date: Thu Jan 01 00:00:01 1970 +0000
560 files: a f
567 files: a f
561 description:
568 description:
562 a
569 a
563
570
564
571
565 $ cd ..
572 $ cd ..
566
573
567 log --follow tests
574 log --follow tests
568
575
569 $ hg init follow
576 $ hg init follow
570 $ cd follow
577 $ cd follow
571
578
572 $ echo base > base
579 $ echo base > base
573 $ hg ci -Ambase -d '1 0'
580 $ hg ci -Ambase -d '1 0'
574 adding base
581 adding base
575
582
576 $ echo r1 >> base
583 $ echo r1 >> base
577 $ hg ci -Amr1 -d '1 0'
584 $ hg ci -Amr1 -d '1 0'
578 $ echo r2 >> base
585 $ echo r2 >> base
579 $ hg ci -Amr2 -d '1 0'
586 $ hg ci -Amr2 -d '1 0'
580
587
581 $ hg up -C 1
588 $ hg up -C 1
582 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
589 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
583 $ echo b1 > b1
590 $ echo b1 > b1
584 $ hg ci -Amb1 -d '1 0'
591 $ hg ci -Amb1 -d '1 0'
585 adding b1
592 adding b1
586 created new head
593 created new head
587
594
588
595
589 log -f
596 log -f
590
597
591 $ hg log -f
598 $ hg log -f
592 changeset: 3:e62f78d544b4
599 changeset: 3:e62f78d544b4
593 tag: tip
600 tag: tip
594 parent: 1:3d5bf5654eda
601 parent: 1:3d5bf5654eda
595 user: test
602 user: test
596 date: Thu Jan 01 00:00:01 1970 +0000
603 date: Thu Jan 01 00:00:01 1970 +0000
597 summary: b1
604 summary: b1
598
605
599 changeset: 1:3d5bf5654eda
606 changeset: 1:3d5bf5654eda
600 user: test
607 user: test
601 date: Thu Jan 01 00:00:01 1970 +0000
608 date: Thu Jan 01 00:00:01 1970 +0000
602 summary: r1
609 summary: r1
603
610
604 changeset: 0:67e992f2c4f3
611 changeset: 0:67e992f2c4f3
605 user: test
612 user: test
606 date: Thu Jan 01 00:00:01 1970 +0000
613 date: Thu Jan 01 00:00:01 1970 +0000
607 summary: base
614 summary: base
608
615
609
616
610
617
611 log -f -r 1:tip
618 log -f -r 1:tip
612
619
613 $ hg up -C 0
620 $ hg up -C 0
614 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
621 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
615 $ echo b2 > b2
622 $ echo b2 > b2
616 $ hg ci -Amb2 -d '1 0'
623 $ hg ci -Amb2 -d '1 0'
617 adding b2
624 adding b2
618 created new head
625 created new head
619 $ hg log -f -r 1:tip
626 $ hg log -f -r 1:tip
620 changeset: 1:3d5bf5654eda
627 changeset: 1:3d5bf5654eda
621 user: test
628 user: test
622 date: Thu Jan 01 00:00:01 1970 +0000
629 date: Thu Jan 01 00:00:01 1970 +0000
623 summary: r1
630 summary: r1
624
631
625 changeset: 2:60c670bf5b30
632 changeset: 2:60c670bf5b30
626 user: test
633 user: test
627 date: Thu Jan 01 00:00:01 1970 +0000
634 date: Thu Jan 01 00:00:01 1970 +0000
628 summary: r2
635 summary: r2
629
636
630 changeset: 3:e62f78d544b4
637 changeset: 3:e62f78d544b4
631 parent: 1:3d5bf5654eda
638 parent: 1:3d5bf5654eda
632 user: test
639 user: test
633 date: Thu Jan 01 00:00:01 1970 +0000
640 date: Thu Jan 01 00:00:01 1970 +0000
634 summary: b1
641 summary: b1
635
642
636
643
637
644
638 log -f -r null
645 log -f -r null
639
646
640 $ hg log -f -r null
647 $ hg log -f -r null
641 changeset: -1:000000000000
648 changeset: -1:000000000000
642 user:
649 user:
643 date: Thu Jan 01 00:00:00 1970 +0000
650 date: Thu Jan 01 00:00:00 1970 +0000
644
651
645 $ hg log -f -r null -G
652 $ hg log -f -r null -G
646 o changeset: -1:000000000000
653 o changeset: -1:000000000000
647 user:
654 user:
648 date: Thu Jan 01 00:00:00 1970 +0000
655 date: Thu Jan 01 00:00:00 1970 +0000
649
656
650
657
651
658
652 log -r . with two parents
659 log -r . with two parents
653
660
654 $ hg up -C 3
661 $ hg up -C 3
655 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
662 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
656 $ hg merge tip
663 $ hg merge tip
657 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
664 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
658 (branch merge, don't forget to commit)
665 (branch merge, don't forget to commit)
659 $ hg log -r .
666 $ hg log -r .
660 changeset: 3:e62f78d544b4
667 changeset: 3:e62f78d544b4
661 parent: 1:3d5bf5654eda
668 parent: 1:3d5bf5654eda
662 user: test
669 user: test
663 date: Thu Jan 01 00:00:01 1970 +0000
670 date: Thu Jan 01 00:00:01 1970 +0000
664 summary: b1
671 summary: b1
665
672
666
673
667
674
668 log -r . with one parent
675 log -r . with one parent
669
676
670 $ hg ci -mm12 -d '1 0'
677 $ hg ci -mm12 -d '1 0'
671 $ hg log -r .
678 $ hg log -r .
672 changeset: 5:302e9dd6890d
679 changeset: 5:302e9dd6890d
673 tag: tip
680 tag: tip
674 parent: 3:e62f78d544b4
681 parent: 3:e62f78d544b4
675 parent: 4:ddb82e70d1a1
682 parent: 4:ddb82e70d1a1
676 user: test
683 user: test
677 date: Thu Jan 01 00:00:01 1970 +0000
684 date: Thu Jan 01 00:00:01 1970 +0000
678 summary: m12
685 summary: m12
679
686
680
687
681 $ echo postm >> b1
688 $ echo postm >> b1
682 $ hg ci -Amb1.1 -d'1 0'
689 $ hg ci -Amb1.1 -d'1 0'
683
690
684
691
685 log --follow-first
692 log --follow-first
686
693
687 $ hg log --follow-first
694 $ hg log --follow-first
688 changeset: 6:2404bbcab562
695 changeset: 6:2404bbcab562
689 tag: tip
696 tag: tip
690 user: test
697 user: test
691 date: Thu Jan 01 00:00:01 1970 +0000
698 date: Thu Jan 01 00:00:01 1970 +0000
692 summary: b1.1
699 summary: b1.1
693
700
694 changeset: 5:302e9dd6890d
701 changeset: 5:302e9dd6890d
695 parent: 3:e62f78d544b4
702 parent: 3:e62f78d544b4
696 parent: 4:ddb82e70d1a1
703 parent: 4:ddb82e70d1a1
697 user: test
704 user: test
698 date: Thu Jan 01 00:00:01 1970 +0000
705 date: Thu Jan 01 00:00:01 1970 +0000
699 summary: m12
706 summary: m12
700
707
701 changeset: 3:e62f78d544b4
708 changeset: 3:e62f78d544b4
702 parent: 1:3d5bf5654eda
709 parent: 1:3d5bf5654eda
703 user: test
710 user: test
704 date: Thu Jan 01 00:00:01 1970 +0000
711 date: Thu Jan 01 00:00:01 1970 +0000
705 summary: b1
712 summary: b1
706
713
707 changeset: 1:3d5bf5654eda
714 changeset: 1:3d5bf5654eda
708 user: test
715 user: test
709 date: Thu Jan 01 00:00:01 1970 +0000
716 date: Thu Jan 01 00:00:01 1970 +0000
710 summary: r1
717 summary: r1
711
718
712 changeset: 0:67e992f2c4f3
719 changeset: 0:67e992f2c4f3
713 user: test
720 user: test
714 date: Thu Jan 01 00:00:01 1970 +0000
721 date: Thu Jan 01 00:00:01 1970 +0000
715 summary: base
722 summary: base
716
723
717
724
718
725
719 log -P 2
726 log -P 2
720
727
721 $ hg log -P 2
728 $ hg log -P 2
722 changeset: 6:2404bbcab562
729 changeset: 6:2404bbcab562
723 tag: tip
730 tag: tip
724 user: test
731 user: test
725 date: Thu Jan 01 00:00:01 1970 +0000
732 date: Thu Jan 01 00:00:01 1970 +0000
726 summary: b1.1
733 summary: b1.1
727
734
728 changeset: 5:302e9dd6890d
735 changeset: 5:302e9dd6890d
729 parent: 3:e62f78d544b4
736 parent: 3:e62f78d544b4
730 parent: 4:ddb82e70d1a1
737 parent: 4:ddb82e70d1a1
731 user: test
738 user: test
732 date: Thu Jan 01 00:00:01 1970 +0000
739 date: Thu Jan 01 00:00:01 1970 +0000
733 summary: m12
740 summary: m12
734
741
735 changeset: 4:ddb82e70d1a1
742 changeset: 4:ddb82e70d1a1
736 parent: 0:67e992f2c4f3
743 parent: 0:67e992f2c4f3
737 user: test
744 user: test
738 date: Thu Jan 01 00:00:01 1970 +0000
745 date: Thu Jan 01 00:00:01 1970 +0000
739 summary: b2
746 summary: b2
740
747
741 changeset: 3:e62f78d544b4
748 changeset: 3:e62f78d544b4
742 parent: 1:3d5bf5654eda
749 parent: 1:3d5bf5654eda
743 user: test
750 user: test
744 date: Thu Jan 01 00:00:01 1970 +0000
751 date: Thu Jan 01 00:00:01 1970 +0000
745 summary: b1
752 summary: b1
746
753
747
754
748
755
749 log -r tip -p --git
756 log -r tip -p --git
750
757
751 $ hg log -r tip -p --git
758 $ hg log -r tip -p --git
752 changeset: 6:2404bbcab562
759 changeset: 6:2404bbcab562
753 tag: tip
760 tag: tip
754 user: test
761 user: test
755 date: Thu Jan 01 00:00:01 1970 +0000
762 date: Thu Jan 01 00:00:01 1970 +0000
756 summary: b1.1
763 summary: b1.1
757
764
758 diff --git a/b1 b/b1
765 diff --git a/b1 b/b1
759 --- a/b1
766 --- a/b1
760 +++ b/b1
767 +++ b/b1
761 @@ -1,1 +1,2 @@
768 @@ -1,1 +1,2 @@
762 b1
769 b1
763 +postm
770 +postm
764
771
765
772
766
773
767 log -r ""
774 log -r ""
768
775
769 $ hg log -r ''
776 $ hg log -r ''
770 hg: parse error: empty query
777 hg: parse error: empty query
771 [255]
778 [255]
772
779
773 log -r <some unknown node id>
780 log -r <some unknown node id>
774
781
775 $ hg log -r 1000000000000000000000000000000000000000
782 $ hg log -r 1000000000000000000000000000000000000000
776 abort: unknown revision '1000000000000000000000000000000000000000'!
783 abort: unknown revision '1000000000000000000000000000000000000000'!
777 [255]
784 [255]
778
785
779 log -k r1
786 log -k r1
780
787
781 $ hg log -k r1
788 $ hg log -k r1
782 changeset: 1:3d5bf5654eda
789 changeset: 1:3d5bf5654eda
783 user: test
790 user: test
784 date: Thu Jan 01 00:00:01 1970 +0000
791 date: Thu Jan 01 00:00:01 1970 +0000
785 summary: r1
792 summary: r1
786
793
787 log -p -l2 --color=always
794 log -p -l2 --color=always
788
795
789 $ hg --config extensions.color= --config color.mode=ansi \
796 $ hg --config extensions.color= --config color.mode=ansi \
790 > log -p -l2 --color=always
797 > log -p -l2 --color=always
791 \x1b[0;33mchangeset: 6:2404bbcab562\x1b[0m (esc)
798 \x1b[0;33mchangeset: 6:2404bbcab562\x1b[0m (esc)
792 tag: tip
799 tag: tip
793 user: test
800 user: test
794 date: Thu Jan 01 00:00:01 1970 +0000
801 date: Thu Jan 01 00:00:01 1970 +0000
795 summary: b1.1
802 summary: b1.1
796
803
797 \x1b[0;1mdiff -r 302e9dd6890d -r 2404bbcab562 b1\x1b[0m (esc)
804 \x1b[0;1mdiff -r 302e9dd6890d -r 2404bbcab562 b1\x1b[0m (esc)
798 \x1b[0;31;1m--- a/b1 Thu Jan 01 00:00:01 1970 +0000\x1b[0m (esc)
805 \x1b[0;31;1m--- a/b1 Thu Jan 01 00:00:01 1970 +0000\x1b[0m (esc)
799 \x1b[0;32;1m+++ b/b1 Thu Jan 01 00:00:01 1970 +0000\x1b[0m (esc)
806 \x1b[0;32;1m+++ b/b1 Thu Jan 01 00:00:01 1970 +0000\x1b[0m (esc)
800 \x1b[0;35m@@ -1,1 +1,2 @@\x1b[0m (esc)
807 \x1b[0;35m@@ -1,1 +1,2 @@\x1b[0m (esc)
801 b1
808 b1
802 \x1b[0;32m+postm\x1b[0m (esc)
809 \x1b[0;32m+postm\x1b[0m (esc)
803
810
804 \x1b[0;33mchangeset: 5:302e9dd6890d\x1b[0m (esc)
811 \x1b[0;33mchangeset: 5:302e9dd6890d\x1b[0m (esc)
805 parent: 3:e62f78d544b4
812 parent: 3:e62f78d544b4
806 parent: 4:ddb82e70d1a1
813 parent: 4:ddb82e70d1a1
807 user: test
814 user: test
808 date: Thu Jan 01 00:00:01 1970 +0000
815 date: Thu Jan 01 00:00:01 1970 +0000
809 summary: m12
816 summary: m12
810
817
811 \x1b[0;1mdiff -r e62f78d544b4 -r 302e9dd6890d b2\x1b[0m (esc)
818 \x1b[0;1mdiff -r e62f78d544b4 -r 302e9dd6890d b2\x1b[0m (esc)
812 \x1b[0;31;1m--- /dev/null Thu Jan 01 00:00:00 1970 +0000\x1b[0m (esc)
819 \x1b[0;31;1m--- /dev/null Thu Jan 01 00:00:00 1970 +0000\x1b[0m (esc)
813 \x1b[0;32;1m+++ b/b2 Thu Jan 01 00:00:01 1970 +0000\x1b[0m (esc)
820 \x1b[0;32;1m+++ b/b2 Thu Jan 01 00:00:01 1970 +0000\x1b[0m (esc)
814 \x1b[0;35m@@ -0,0 +1,1 @@\x1b[0m (esc)
821 \x1b[0;35m@@ -0,0 +1,1 @@\x1b[0m (esc)
815 \x1b[0;32m+b2\x1b[0m (esc)
822 \x1b[0;32m+b2\x1b[0m (esc)
816
823
817
824
818
825
819 log -r tip --stat
826 log -r tip --stat
820
827
821 $ hg log -r tip --stat
828 $ hg log -r tip --stat
822 changeset: 6:2404bbcab562
829 changeset: 6:2404bbcab562
823 tag: tip
830 tag: tip
824 user: test
831 user: test
825 date: Thu Jan 01 00:00:01 1970 +0000
832 date: Thu Jan 01 00:00:01 1970 +0000
826 summary: b1.1
833 summary: b1.1
827
834
828 b1 | 1 +
835 b1 | 1 +
829 1 files changed, 1 insertions(+), 0 deletions(-)
836 1 files changed, 1 insertions(+), 0 deletions(-)
830
837
831
838
832 $ cd ..
839 $ cd ..
833
840
834
841
835 User
842 User
836
843
837 $ hg init usertest
844 $ hg init usertest
838 $ cd usertest
845 $ cd usertest
839
846
840 $ echo a > a
847 $ echo a > a
841 $ hg ci -A -m "a" -u "User One <user1@example.org>"
848 $ hg ci -A -m "a" -u "User One <user1@example.org>"
842 adding a
849 adding a
843 $ echo b > b
850 $ echo b > b
844 $ hg ci -A -m "b" -u "User Two <user2@example.org>"
851 $ hg ci -A -m "b" -u "User Two <user2@example.org>"
845 adding b
852 adding b
846
853
847 $ hg log -u "User One <user1@example.org>"
854 $ hg log -u "User One <user1@example.org>"
848 changeset: 0:29a4c94f1924
855 changeset: 0:29a4c94f1924
849 user: User One <user1@example.org>
856 user: User One <user1@example.org>
850 date: Thu Jan 01 00:00:00 1970 +0000
857 date: Thu Jan 01 00:00:00 1970 +0000
851 summary: a
858 summary: a
852
859
853 $ hg log -u "user1" -u "user2"
860 $ hg log -u "user1" -u "user2"
854 changeset: 1:e834b5e69c0e
861 changeset: 1:e834b5e69c0e
855 tag: tip
862 tag: tip
856 user: User Two <user2@example.org>
863 user: User Two <user2@example.org>
857 date: Thu Jan 01 00:00:00 1970 +0000
864 date: Thu Jan 01 00:00:00 1970 +0000
858 summary: b
865 summary: b
859
866
860 changeset: 0:29a4c94f1924
867 changeset: 0:29a4c94f1924
861 user: User One <user1@example.org>
868 user: User One <user1@example.org>
862 date: Thu Jan 01 00:00:00 1970 +0000
869 date: Thu Jan 01 00:00:00 1970 +0000
863 summary: a
870 summary: a
864
871
865 $ hg log -u "user3"
872 $ hg log -u "user3"
866
873
867 $ cd ..
874 $ cd ..
868
875
869 $ hg init branches
876 $ hg init branches
870 $ cd branches
877 $ cd branches
871
878
872 $ echo a > a
879 $ echo a > a
873 $ hg ci -A -m "commit on default"
880 $ hg ci -A -m "commit on default"
874 adding a
881 adding a
875 $ hg branch test
882 $ hg branch test
876 marked working directory as branch test
883 marked working directory as branch test
877 (branches are permanent and global, did you want a bookmark?)
884 (branches are permanent and global, did you want a bookmark?)
878 $ echo b > b
885 $ echo b > b
879 $ hg ci -A -m "commit on test"
886 $ hg ci -A -m "commit on test"
880 adding b
887 adding b
881
888
882 $ hg up default
889 $ hg up default
883 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
890 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
884 $ echo c > c
891 $ echo c > c
885 $ hg ci -A -m "commit on default"
892 $ hg ci -A -m "commit on default"
886 adding c
893 adding c
887 $ hg up test
894 $ hg up test
888 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
895 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
889 $ echo c > c
896 $ echo c > c
890 $ hg ci -A -m "commit on test"
897 $ hg ci -A -m "commit on test"
891 adding c
898 adding c
892
899
893
900
894 log -b default
901 log -b default
895
902
896 $ hg log -b default
903 $ hg log -b default
897 changeset: 2:c3a4f03cc9a7
904 changeset: 2:c3a4f03cc9a7
898 parent: 0:24427303d56f
905 parent: 0:24427303d56f
899 user: test
906 user: test
900 date: Thu Jan 01 00:00:00 1970 +0000
907 date: Thu Jan 01 00:00:00 1970 +0000
901 summary: commit on default
908 summary: commit on default
902
909
903 changeset: 0:24427303d56f
910 changeset: 0:24427303d56f
904 user: test
911 user: test
905 date: Thu Jan 01 00:00:00 1970 +0000
912 date: Thu Jan 01 00:00:00 1970 +0000
906 summary: commit on default
913 summary: commit on default
907
914
908
915
909
916
910 log -b test
917 log -b test
911
918
912 $ hg log -b test
919 $ hg log -b test
913 changeset: 3:f5d8de11c2e2
920 changeset: 3:f5d8de11c2e2
914 branch: test
921 branch: test
915 tag: tip
922 tag: tip
916 parent: 1:d32277701ccb
923 parent: 1:d32277701ccb
917 user: test
924 user: test
918 date: Thu Jan 01 00:00:00 1970 +0000
925 date: Thu Jan 01 00:00:00 1970 +0000
919 summary: commit on test
926 summary: commit on test
920
927
921 changeset: 1:d32277701ccb
928 changeset: 1:d32277701ccb
922 branch: test
929 branch: test
923 user: test
930 user: test
924 date: Thu Jan 01 00:00:00 1970 +0000
931 date: Thu Jan 01 00:00:00 1970 +0000
925 summary: commit on test
932 summary: commit on test
926
933
927
934
928
935
929 log -b dummy
936 log -b dummy
930
937
931 $ hg log -b dummy
938 $ hg log -b dummy
932 abort: unknown revision 'dummy'!
939 abort: unknown revision 'dummy'!
933 [255]
940 [255]
934
941
935
942
936 log -b .
943 log -b .
937
944
938 $ hg log -b .
945 $ hg log -b .
939 changeset: 3:f5d8de11c2e2
946 changeset: 3:f5d8de11c2e2
940 branch: test
947 branch: test
941 tag: tip
948 tag: tip
942 parent: 1:d32277701ccb
949 parent: 1:d32277701ccb
943 user: test
950 user: test
944 date: Thu Jan 01 00:00:00 1970 +0000
951 date: Thu Jan 01 00:00:00 1970 +0000
945 summary: commit on test
952 summary: commit on test
946
953
947 changeset: 1:d32277701ccb
954 changeset: 1:d32277701ccb
948 branch: test
955 branch: test
949 user: test
956 user: test
950 date: Thu Jan 01 00:00:00 1970 +0000
957 date: Thu Jan 01 00:00:00 1970 +0000
951 summary: commit on test
958 summary: commit on test
952
959
953
960
954
961
955 log -b default -b test
962 log -b default -b test
956
963
957 $ hg log -b default -b test
964 $ hg log -b default -b test
958 changeset: 3:f5d8de11c2e2
965 changeset: 3:f5d8de11c2e2
959 branch: test
966 branch: test
960 tag: tip
967 tag: tip
961 parent: 1:d32277701ccb
968 parent: 1:d32277701ccb
962 user: test
969 user: test
963 date: Thu Jan 01 00:00:00 1970 +0000
970 date: Thu Jan 01 00:00:00 1970 +0000
964 summary: commit on test
971 summary: commit on test
965
972
966 changeset: 2:c3a4f03cc9a7
973 changeset: 2:c3a4f03cc9a7
967 parent: 0:24427303d56f
974 parent: 0:24427303d56f
968 user: test
975 user: test
969 date: Thu Jan 01 00:00:00 1970 +0000
976 date: Thu Jan 01 00:00:00 1970 +0000
970 summary: commit on default
977 summary: commit on default
971
978
972 changeset: 1:d32277701ccb
979 changeset: 1:d32277701ccb
973 branch: test
980 branch: test
974 user: test
981 user: test
975 date: Thu Jan 01 00:00:00 1970 +0000
982 date: Thu Jan 01 00:00:00 1970 +0000
976 summary: commit on test
983 summary: commit on test
977
984
978 changeset: 0:24427303d56f
985 changeset: 0:24427303d56f
979 user: test
986 user: test
980 date: Thu Jan 01 00:00:00 1970 +0000
987 date: Thu Jan 01 00:00:00 1970 +0000
981 summary: commit on default
988 summary: commit on default
982
989
983
990
984
991
985 log -b default -b .
992 log -b default -b .
986
993
987 $ hg log -b default -b .
994 $ hg log -b default -b .
988 changeset: 3:f5d8de11c2e2
995 changeset: 3:f5d8de11c2e2
989 branch: test
996 branch: test
990 tag: tip
997 tag: tip
991 parent: 1:d32277701ccb
998 parent: 1:d32277701ccb
992 user: test
999 user: test
993 date: Thu Jan 01 00:00:00 1970 +0000
1000 date: Thu Jan 01 00:00:00 1970 +0000
994 summary: commit on test
1001 summary: commit on test
995
1002
996 changeset: 2:c3a4f03cc9a7
1003 changeset: 2:c3a4f03cc9a7
997 parent: 0:24427303d56f
1004 parent: 0:24427303d56f
998 user: test
1005 user: test
999 date: Thu Jan 01 00:00:00 1970 +0000
1006 date: Thu Jan 01 00:00:00 1970 +0000
1000 summary: commit on default
1007 summary: commit on default
1001
1008
1002 changeset: 1:d32277701ccb
1009 changeset: 1:d32277701ccb
1003 branch: test
1010 branch: test
1004 user: test
1011 user: test
1005 date: Thu Jan 01 00:00:00 1970 +0000
1012 date: Thu Jan 01 00:00:00 1970 +0000
1006 summary: commit on test
1013 summary: commit on test
1007
1014
1008 changeset: 0:24427303d56f
1015 changeset: 0:24427303d56f
1009 user: test
1016 user: test
1010 date: Thu Jan 01 00:00:00 1970 +0000
1017 date: Thu Jan 01 00:00:00 1970 +0000
1011 summary: commit on default
1018 summary: commit on default
1012
1019
1013
1020
1014
1021
1015 log -b . -b test
1022 log -b . -b test
1016
1023
1017 $ hg log -b . -b test
1024 $ hg log -b . -b test
1018 changeset: 3:f5d8de11c2e2
1025 changeset: 3:f5d8de11c2e2
1019 branch: test
1026 branch: test
1020 tag: tip
1027 tag: tip
1021 parent: 1:d32277701ccb
1028 parent: 1:d32277701ccb
1022 user: test
1029 user: test
1023 date: Thu Jan 01 00:00:00 1970 +0000
1030 date: Thu Jan 01 00:00:00 1970 +0000
1024 summary: commit on test
1031 summary: commit on test
1025
1032
1026 changeset: 1:d32277701ccb
1033 changeset: 1:d32277701ccb
1027 branch: test
1034 branch: test
1028 user: test
1035 user: test
1029 date: Thu Jan 01 00:00:00 1970 +0000
1036 date: Thu Jan 01 00:00:00 1970 +0000
1030 summary: commit on test
1037 summary: commit on test
1031
1038
1032
1039
1033
1040
1034 log -b 2
1041 log -b 2
1035
1042
1036 $ hg log -b 2
1043 $ hg log -b 2
1037 changeset: 2:c3a4f03cc9a7
1044 changeset: 2:c3a4f03cc9a7
1038 parent: 0:24427303d56f
1045 parent: 0:24427303d56f
1039 user: test
1046 user: test
1040 date: Thu Jan 01 00:00:00 1970 +0000
1047 date: Thu Jan 01 00:00:00 1970 +0000
1041 summary: commit on default
1048 summary: commit on default
1042
1049
1043 changeset: 0:24427303d56f
1050 changeset: 0:24427303d56f
1044 user: test
1051 user: test
1045 date: Thu Jan 01 00:00:00 1970 +0000
1052 date: Thu Jan 01 00:00:00 1970 +0000
1046 summary: commit on default
1053 summary: commit on default
1047
1054
1048 #if gettext
1055 #if gettext
1049
1056
1050 Test that all log names are translated (e.g. branches, bookmarks, tags):
1057 Test that all log names are translated (e.g. branches, bookmarks, tags):
1051
1058
1052 $ hg bookmark babar -r tip
1059 $ hg bookmark babar -r tip
1053
1060
1054 $ HGENCODING=UTF-8 LANGUAGE=de hg log -r tip
1061 $ HGENCODING=UTF-8 LANGUAGE=de hg log -r tip
1055 \xc3\x84nderung: 3:f5d8de11c2e2 (esc)
1062 \xc3\x84nderung: 3:f5d8de11c2e2 (esc)
1056 Zweig: test
1063 Zweig: test
1057 Lesezeichen: babar
1064 Lesezeichen: babar
1058 Marke: tip
1065 Marke: tip
1059 Vorg\xc3\xa4nger: 1:d32277701ccb (esc)
1066 Vorg\xc3\xa4nger: 1:d32277701ccb (esc)
1060 Nutzer: test
1067 Nutzer: test
1061 Datum: Thu Jan 01 00:00:00 1970 +0000
1068 Datum: Thu Jan 01 00:00:00 1970 +0000
1062 Zusammenfassung: commit on test
1069 Zusammenfassung: commit on test
1063
1070
1064 $ hg bookmark -d babar
1071 $ hg bookmark -d babar
1065
1072
1066 #endif
1073 #endif
1067
1074
1068 log -p --cwd dir (in subdir)
1075 log -p --cwd dir (in subdir)
1069
1076
1070 $ mkdir dir
1077 $ mkdir dir
1071 $ hg log -p --cwd dir
1078 $ hg log -p --cwd dir
1072 changeset: 3:f5d8de11c2e2
1079 changeset: 3:f5d8de11c2e2
1073 branch: test
1080 branch: test
1074 tag: tip
1081 tag: tip
1075 parent: 1:d32277701ccb
1082 parent: 1:d32277701ccb
1076 user: test
1083 user: test
1077 date: Thu Jan 01 00:00:00 1970 +0000
1084 date: Thu Jan 01 00:00:00 1970 +0000
1078 summary: commit on test
1085 summary: commit on test
1079
1086
1080 diff -r d32277701ccb -r f5d8de11c2e2 c
1087 diff -r d32277701ccb -r f5d8de11c2e2 c
1081 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1088 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1082 +++ b/c Thu Jan 01 00:00:00 1970 +0000
1089 +++ b/c Thu Jan 01 00:00:00 1970 +0000
1083 @@ -0,0 +1,1 @@
1090 @@ -0,0 +1,1 @@
1084 +c
1091 +c
1085
1092
1086 changeset: 2:c3a4f03cc9a7
1093 changeset: 2:c3a4f03cc9a7
1087 parent: 0:24427303d56f
1094 parent: 0:24427303d56f
1088 user: test
1095 user: test
1089 date: Thu Jan 01 00:00:00 1970 +0000
1096 date: Thu Jan 01 00:00:00 1970 +0000
1090 summary: commit on default
1097 summary: commit on default
1091
1098
1092 diff -r 24427303d56f -r c3a4f03cc9a7 c
1099 diff -r 24427303d56f -r c3a4f03cc9a7 c
1093 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1100 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1094 +++ b/c Thu Jan 01 00:00:00 1970 +0000
1101 +++ b/c Thu Jan 01 00:00:00 1970 +0000
1095 @@ -0,0 +1,1 @@
1102 @@ -0,0 +1,1 @@
1096 +c
1103 +c
1097
1104
1098 changeset: 1:d32277701ccb
1105 changeset: 1:d32277701ccb
1099 branch: test
1106 branch: test
1100 user: test
1107 user: test
1101 date: Thu Jan 01 00:00:00 1970 +0000
1108 date: Thu Jan 01 00:00:00 1970 +0000
1102 summary: commit on test
1109 summary: commit on test
1103
1110
1104 diff -r 24427303d56f -r d32277701ccb b
1111 diff -r 24427303d56f -r d32277701ccb b
1105 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1112 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1106 +++ b/b Thu Jan 01 00:00:00 1970 +0000
1113 +++ b/b Thu Jan 01 00:00:00 1970 +0000
1107 @@ -0,0 +1,1 @@
1114 @@ -0,0 +1,1 @@
1108 +b
1115 +b
1109
1116
1110 changeset: 0:24427303d56f
1117 changeset: 0:24427303d56f
1111 user: test
1118 user: test
1112 date: Thu Jan 01 00:00:00 1970 +0000
1119 date: Thu Jan 01 00:00:00 1970 +0000
1113 summary: commit on default
1120 summary: commit on default
1114
1121
1115 diff -r 000000000000 -r 24427303d56f a
1122 diff -r 000000000000 -r 24427303d56f a
1116 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1123 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1117 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1124 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1118 @@ -0,0 +1,1 @@
1125 @@ -0,0 +1,1 @@
1119 +a
1126 +a
1120
1127
1121
1128
1122
1129
1123 log -p -R repo
1130 log -p -R repo
1124
1131
1125 $ cd dir
1132 $ cd dir
1126 $ hg log -p -R .. ../a
1133 $ hg log -p -R .. ../a
1127 changeset: 0:24427303d56f
1134 changeset: 0:24427303d56f
1128 user: test
1135 user: test
1129 date: Thu Jan 01 00:00:00 1970 +0000
1136 date: Thu Jan 01 00:00:00 1970 +0000
1130 summary: commit on default
1137 summary: commit on default
1131
1138
1132 diff -r 000000000000 -r 24427303d56f a
1139 diff -r 000000000000 -r 24427303d56f a
1133 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1140 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1134 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1141 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1135 @@ -0,0 +1,1 @@
1142 @@ -0,0 +1,1 @@
1136 +a
1143 +a
1137
1144
1138
1145
1139 $ cd ../..
1146 $ cd ../..
1140
1147
1141 $ hg init follow2
1148 $ hg init follow2
1142 $ cd follow2
1149 $ cd follow2
1143
1150
1144 # Build the following history:
1151 # Build the following history:
1145 # tip - o - x - o - x - x
1152 # tip - o - x - o - x - x
1146 # \ /
1153 # \ /
1147 # o - o - o - x
1154 # o - o - o - x
1148 # \ /
1155 # \ /
1149 # o
1156 # o
1150 #
1157 #
1151 # Where "o" is a revision containing "foo" and
1158 # Where "o" is a revision containing "foo" and
1152 # "x" is a revision without "foo"
1159 # "x" is a revision without "foo"
1153
1160
1154 $ touch init
1161 $ touch init
1155 $ hg ci -A -m "init, unrelated"
1162 $ hg ci -A -m "init, unrelated"
1156 adding init
1163 adding init
1157 $ echo 'foo' > init
1164 $ echo 'foo' > init
1158 $ hg ci -m "change, unrelated"
1165 $ hg ci -m "change, unrelated"
1159 $ echo 'foo' > foo
1166 $ echo 'foo' > foo
1160 $ hg ci -A -m "add unrelated old foo"
1167 $ hg ci -A -m "add unrelated old foo"
1161 adding foo
1168 adding foo
1162 $ hg rm foo
1169 $ hg rm foo
1163 $ hg ci -m "delete foo, unrelated"
1170 $ hg ci -m "delete foo, unrelated"
1164 $ echo 'related' > foo
1171 $ echo 'related' > foo
1165 $ hg ci -A -m "add foo, related"
1172 $ hg ci -A -m "add foo, related"
1166 adding foo
1173 adding foo
1167
1174
1168 $ hg up 0
1175 $ hg up 0
1169 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1176 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1170 $ touch branch
1177 $ touch branch
1171 $ hg ci -A -m "first branch, unrelated"
1178 $ hg ci -A -m "first branch, unrelated"
1172 adding branch
1179 adding branch
1173 created new head
1180 created new head
1174 $ touch foo
1181 $ touch foo
1175 $ hg ci -A -m "create foo, related"
1182 $ hg ci -A -m "create foo, related"
1176 adding foo
1183 adding foo
1177 $ echo 'change' > foo
1184 $ echo 'change' > foo
1178 $ hg ci -m "change foo, related"
1185 $ hg ci -m "change foo, related"
1179
1186
1180 $ hg up 6
1187 $ hg up 6
1181 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1188 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1182 $ echo 'change foo in branch' > foo
1189 $ echo 'change foo in branch' > foo
1183 $ hg ci -m "change foo in branch, related"
1190 $ hg ci -m "change foo in branch, related"
1184 created new head
1191 created new head
1185 $ hg merge 7
1192 $ hg merge 7
1186 merging foo
1193 merging foo
1187 warning: conflicts during merge.
1194 warning: conflicts during merge.
1188 merging foo incomplete! (edit conflicts, then use 'hg resolve --mark')
1195 merging foo incomplete! (edit conflicts, then use 'hg resolve --mark')
1189 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
1196 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
1190 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
1197 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
1191 [1]
1198 [1]
1192 $ echo 'merge 1' > foo
1199 $ echo 'merge 1' > foo
1193 $ hg resolve -m foo
1200 $ hg resolve -m foo
1194 (no more unresolved files)
1201 (no more unresolved files)
1195 $ hg ci -m "First merge, related"
1202 $ hg ci -m "First merge, related"
1196
1203
1197 $ hg merge 4
1204 $ hg merge 4
1198 merging foo
1205 merging foo
1199 warning: conflicts during merge.
1206 warning: conflicts during merge.
1200 merging foo incomplete! (edit conflicts, then use 'hg resolve --mark')
1207 merging foo incomplete! (edit conflicts, then use 'hg resolve --mark')
1201 1 files updated, 0 files merged, 0 files removed, 1 files unresolved
1208 1 files updated, 0 files merged, 0 files removed, 1 files unresolved
1202 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
1209 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
1203 [1]
1210 [1]
1204 $ echo 'merge 2' > foo
1211 $ echo 'merge 2' > foo
1205 $ hg resolve -m foo
1212 $ hg resolve -m foo
1206 (no more unresolved files)
1213 (no more unresolved files)
1207 $ hg ci -m "Last merge, related"
1214 $ hg ci -m "Last merge, related"
1208
1215
1209 $ hg log --graph
1216 $ hg log --graph
1210 @ changeset: 10:4dae8563d2c5
1217 @ changeset: 10:4dae8563d2c5
1211 |\ tag: tip
1218 |\ tag: tip
1212 | | parent: 9:7b35701b003e
1219 | | parent: 9:7b35701b003e
1213 | | parent: 4:88176d361b69
1220 | | parent: 4:88176d361b69
1214 | | user: test
1221 | | user: test
1215 | | date: Thu Jan 01 00:00:00 1970 +0000
1222 | | date: Thu Jan 01 00:00:00 1970 +0000
1216 | | summary: Last merge, related
1223 | | summary: Last merge, related
1217 | |
1224 | |
1218 | o changeset: 9:7b35701b003e
1225 | o changeset: 9:7b35701b003e
1219 | |\ parent: 8:e5416ad8a855
1226 | |\ parent: 8:e5416ad8a855
1220 | | | parent: 7:87fe3144dcfa
1227 | | | parent: 7:87fe3144dcfa
1221 | | | user: test
1228 | | | user: test
1222 | | | date: Thu Jan 01 00:00:00 1970 +0000
1229 | | | date: Thu Jan 01 00:00:00 1970 +0000
1223 | | | summary: First merge, related
1230 | | | summary: First merge, related
1224 | | |
1231 | | |
1225 | | o changeset: 8:e5416ad8a855
1232 | | o changeset: 8:e5416ad8a855
1226 | | | parent: 6:dc6c325fe5ee
1233 | | | parent: 6:dc6c325fe5ee
1227 | | | user: test
1234 | | | user: test
1228 | | | date: Thu Jan 01 00:00:00 1970 +0000
1235 | | | date: Thu Jan 01 00:00:00 1970 +0000
1229 | | | summary: change foo in branch, related
1236 | | | summary: change foo in branch, related
1230 | | |
1237 | | |
1231 | o | changeset: 7:87fe3144dcfa
1238 | o | changeset: 7:87fe3144dcfa
1232 | |/ user: test
1239 | |/ user: test
1233 | | date: Thu Jan 01 00:00:00 1970 +0000
1240 | | date: Thu Jan 01 00:00:00 1970 +0000
1234 | | summary: change foo, related
1241 | | summary: change foo, related
1235 | |
1242 | |
1236 | o changeset: 6:dc6c325fe5ee
1243 | o changeset: 6:dc6c325fe5ee
1237 | | user: test
1244 | | user: test
1238 | | date: Thu Jan 01 00:00:00 1970 +0000
1245 | | date: Thu Jan 01 00:00:00 1970 +0000
1239 | | summary: create foo, related
1246 | | summary: create foo, related
1240 | |
1247 | |
1241 | o changeset: 5:73db34516eb9
1248 | o changeset: 5:73db34516eb9
1242 | | parent: 0:e87515fd044a
1249 | | parent: 0:e87515fd044a
1243 | | user: test
1250 | | user: test
1244 | | date: Thu Jan 01 00:00:00 1970 +0000
1251 | | date: Thu Jan 01 00:00:00 1970 +0000
1245 | | summary: first branch, unrelated
1252 | | summary: first branch, unrelated
1246 | |
1253 | |
1247 o | changeset: 4:88176d361b69
1254 o | changeset: 4:88176d361b69
1248 | | user: test
1255 | | user: test
1249 | | date: Thu Jan 01 00:00:00 1970 +0000
1256 | | date: Thu Jan 01 00:00:00 1970 +0000
1250 | | summary: add foo, related
1257 | | summary: add foo, related
1251 | |
1258 | |
1252 o | changeset: 3:dd78ae4afb56
1259 o | changeset: 3:dd78ae4afb56
1253 | | user: test
1260 | | user: test
1254 | | date: Thu Jan 01 00:00:00 1970 +0000
1261 | | date: Thu Jan 01 00:00:00 1970 +0000
1255 | | summary: delete foo, unrelated
1262 | | summary: delete foo, unrelated
1256 | |
1263 | |
1257 o | changeset: 2:c4c64aedf0f7
1264 o | changeset: 2:c4c64aedf0f7
1258 | | user: test
1265 | | user: test
1259 | | date: Thu Jan 01 00:00:00 1970 +0000
1266 | | date: Thu Jan 01 00:00:00 1970 +0000
1260 | | summary: add unrelated old foo
1267 | | summary: add unrelated old foo
1261 | |
1268 | |
1262 o | changeset: 1:e5faa7440653
1269 o | changeset: 1:e5faa7440653
1263 |/ user: test
1270 |/ user: test
1264 | date: Thu Jan 01 00:00:00 1970 +0000
1271 | date: Thu Jan 01 00:00:00 1970 +0000
1265 | summary: change, unrelated
1272 | summary: change, unrelated
1266 |
1273 |
1267 o changeset: 0:e87515fd044a
1274 o changeset: 0:e87515fd044a
1268 user: test
1275 user: test
1269 date: Thu Jan 01 00:00:00 1970 +0000
1276 date: Thu Jan 01 00:00:00 1970 +0000
1270 summary: init, unrelated
1277 summary: init, unrelated
1271
1278
1272
1279
1273 $ hg --traceback log -f foo
1280 $ hg --traceback log -f foo
1274 changeset: 10:4dae8563d2c5
1281 changeset: 10:4dae8563d2c5
1275 tag: tip
1282 tag: tip
1276 parent: 9:7b35701b003e
1283 parent: 9:7b35701b003e
1277 parent: 4:88176d361b69
1284 parent: 4:88176d361b69
1278 user: test
1285 user: test
1279 date: Thu Jan 01 00:00:00 1970 +0000
1286 date: Thu Jan 01 00:00:00 1970 +0000
1280 summary: Last merge, related
1287 summary: Last merge, related
1281
1288
1282 changeset: 9:7b35701b003e
1289 changeset: 9:7b35701b003e
1283 parent: 8:e5416ad8a855
1290 parent: 8:e5416ad8a855
1284 parent: 7:87fe3144dcfa
1291 parent: 7:87fe3144dcfa
1285 user: test
1292 user: test
1286 date: Thu Jan 01 00:00:00 1970 +0000
1293 date: Thu Jan 01 00:00:00 1970 +0000
1287 summary: First merge, related
1294 summary: First merge, related
1288
1295
1289 changeset: 8:e5416ad8a855
1296 changeset: 8:e5416ad8a855
1290 parent: 6:dc6c325fe5ee
1297 parent: 6:dc6c325fe5ee
1291 user: test
1298 user: test
1292 date: Thu Jan 01 00:00:00 1970 +0000
1299 date: Thu Jan 01 00:00:00 1970 +0000
1293 summary: change foo in branch, related
1300 summary: change foo in branch, related
1294
1301
1295 changeset: 7:87fe3144dcfa
1302 changeset: 7:87fe3144dcfa
1296 user: test
1303 user: test
1297 date: Thu Jan 01 00:00:00 1970 +0000
1304 date: Thu Jan 01 00:00:00 1970 +0000
1298 summary: change foo, related
1305 summary: change foo, related
1299
1306
1300 changeset: 6:dc6c325fe5ee
1307 changeset: 6:dc6c325fe5ee
1301 user: test
1308 user: test
1302 date: Thu Jan 01 00:00:00 1970 +0000
1309 date: Thu Jan 01 00:00:00 1970 +0000
1303 summary: create foo, related
1310 summary: create foo, related
1304
1311
1305 changeset: 4:88176d361b69
1312 changeset: 4:88176d361b69
1306 user: test
1313 user: test
1307 date: Thu Jan 01 00:00:00 1970 +0000
1314 date: Thu Jan 01 00:00:00 1970 +0000
1308 summary: add foo, related
1315 summary: add foo, related
1309
1316
1310
1317
1311 Also check when maxrev < lastrevfilelog
1318 Also check when maxrev < lastrevfilelog
1312
1319
1313 $ hg --traceback log -f -r4 foo
1320 $ hg --traceback log -f -r4 foo
1314 changeset: 4:88176d361b69
1321 changeset: 4:88176d361b69
1315 user: test
1322 user: test
1316 date: Thu Jan 01 00:00:00 1970 +0000
1323 date: Thu Jan 01 00:00:00 1970 +0000
1317 summary: add foo, related
1324 summary: add foo, related
1318
1325
1319 $ cd ..
1326 $ cd ..
1320
1327
1321 Issue2383: hg log showing _less_ differences than hg diff
1328 Issue2383: hg log showing _less_ differences than hg diff
1322
1329
1323 $ hg init issue2383
1330 $ hg init issue2383
1324 $ cd issue2383
1331 $ cd issue2383
1325
1332
1326 Create a test repo:
1333 Create a test repo:
1327
1334
1328 $ echo a > a
1335 $ echo a > a
1329 $ hg ci -Am0
1336 $ hg ci -Am0
1330 adding a
1337 adding a
1331 $ echo b > b
1338 $ echo b > b
1332 $ hg ci -Am1
1339 $ hg ci -Am1
1333 adding b
1340 adding b
1334 $ hg co 0
1341 $ hg co 0
1335 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1342 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1336 $ echo b > a
1343 $ echo b > a
1337 $ hg ci -m2
1344 $ hg ci -m2
1338 created new head
1345 created new head
1339
1346
1340 Merge:
1347 Merge:
1341
1348
1342 $ hg merge
1349 $ hg merge
1343 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1350 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1344 (branch merge, don't forget to commit)
1351 (branch merge, don't forget to commit)
1345
1352
1346 Make sure there's a file listed in the merge to trigger the bug:
1353 Make sure there's a file listed in the merge to trigger the bug:
1347
1354
1348 $ echo c > a
1355 $ echo c > a
1349 $ hg ci -m3
1356 $ hg ci -m3
1350
1357
1351 Two files shown here in diff:
1358 Two files shown here in diff:
1352
1359
1353 $ hg diff --rev 2:3
1360 $ hg diff --rev 2:3
1354 diff -r b09be438c43a -r 8e07aafe1edc a
1361 diff -r b09be438c43a -r 8e07aafe1edc a
1355 --- a/a Thu Jan 01 00:00:00 1970 +0000
1362 --- a/a Thu Jan 01 00:00:00 1970 +0000
1356 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1363 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1357 @@ -1,1 +1,1 @@
1364 @@ -1,1 +1,1 @@
1358 -b
1365 -b
1359 +c
1366 +c
1360 diff -r b09be438c43a -r 8e07aafe1edc b
1367 diff -r b09be438c43a -r 8e07aafe1edc b
1361 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1368 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1362 +++ b/b Thu Jan 01 00:00:00 1970 +0000
1369 +++ b/b Thu Jan 01 00:00:00 1970 +0000
1363 @@ -0,0 +1,1 @@
1370 @@ -0,0 +1,1 @@
1364 +b
1371 +b
1365
1372
1366 Diff here should be the same:
1373 Diff here should be the same:
1367
1374
1368 $ hg log -vpr 3
1375 $ hg log -vpr 3
1369 changeset: 3:8e07aafe1edc
1376 changeset: 3:8e07aafe1edc
1370 tag: tip
1377 tag: tip
1371 parent: 2:b09be438c43a
1378 parent: 2:b09be438c43a
1372 parent: 1:925d80f479bb
1379 parent: 1:925d80f479bb
1373 user: test
1380 user: test
1374 date: Thu Jan 01 00:00:00 1970 +0000
1381 date: Thu Jan 01 00:00:00 1970 +0000
1375 files: a
1382 files: a
1376 description:
1383 description:
1377 3
1384 3
1378
1385
1379
1386
1380 diff -r b09be438c43a -r 8e07aafe1edc a
1387 diff -r b09be438c43a -r 8e07aafe1edc a
1381 --- a/a Thu Jan 01 00:00:00 1970 +0000
1388 --- a/a Thu Jan 01 00:00:00 1970 +0000
1382 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1389 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1383 @@ -1,1 +1,1 @@
1390 @@ -1,1 +1,1 @@
1384 -b
1391 -b
1385 +c
1392 +c
1386 diff -r b09be438c43a -r 8e07aafe1edc b
1393 diff -r b09be438c43a -r 8e07aafe1edc b
1387 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1394 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1388 +++ b/b Thu Jan 01 00:00:00 1970 +0000
1395 +++ b/b Thu Jan 01 00:00:00 1970 +0000
1389 @@ -0,0 +1,1 @@
1396 @@ -0,0 +1,1 @@
1390 +b
1397 +b
1391
1398
1392 $ cd ..
1399 $ cd ..
1393
1400
1394 'hg log -r rev fn' when last(filelog(fn)) != rev
1401 'hg log -r rev fn' when last(filelog(fn)) != rev
1395
1402
1396 $ hg init simplelog
1403 $ hg init simplelog
1397 $ cd simplelog
1404 $ cd simplelog
1398 $ echo f > a
1405 $ echo f > a
1399 $ hg ci -Am'a' -d '0 0'
1406 $ hg ci -Am'a' -d '0 0'
1400 adding a
1407 adding a
1401 $ echo f >> a
1408 $ echo f >> a
1402 $ hg ci -Am'a bis' -d '1 0'
1409 $ hg ci -Am'a bis' -d '1 0'
1403
1410
1404 $ hg log -r0 a
1411 $ hg log -r0 a
1405 changeset: 0:9f758d63dcde
1412 changeset: 0:9f758d63dcde
1406 user: test
1413 user: test
1407 date: Thu Jan 01 00:00:00 1970 +0000
1414 date: Thu Jan 01 00:00:00 1970 +0000
1408 summary: a
1415 summary: a
1409
1416
1410 enable obsolete to test hidden feature
1417 enable obsolete to test hidden feature
1411
1418
1412 $ cat >> $HGRCPATH << EOF
1419 $ cat >> $HGRCPATH << EOF
1413 > [experimental]
1420 > [experimental]
1414 > evolution=createmarkers
1421 > evolution=createmarkers
1415 > EOF
1422 > EOF
1416
1423
1417 $ hg log --template='{rev}:{node}\n'
1424 $ hg log --template='{rev}:{node}\n'
1418 1:a765632148dc55d38c35c4f247c618701886cb2f
1425 1:a765632148dc55d38c35c4f247c618701886cb2f
1419 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1426 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1420 $ hg debugobsolete a765632148dc55d38c35c4f247c618701886cb2f
1427 $ hg debugobsolete a765632148dc55d38c35c4f247c618701886cb2f
1421 $ hg up null -q
1428 $ hg up null -q
1422 $ hg log --template='{rev}:{node}\n'
1429 $ hg log --template='{rev}:{node}\n'
1423 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1430 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1424 $ hg log --template='{rev}:{node}\n' --hidden
1431 $ hg log --template='{rev}:{node}\n' --hidden
1425 1:a765632148dc55d38c35c4f247c618701886cb2f
1432 1:a765632148dc55d38c35c4f247c618701886cb2f
1426 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1433 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1427 $ hg log -r a
1434 $ hg log -r a
1428 abort: hidden revision 'a'!
1435 abort: hidden revision 'a'!
1429 (use --hidden to access hidden revisions)
1436 (use --hidden to access hidden revisions)
1430 [255]
1437 [255]
1431
1438
1432 test that parent prevent a changeset to be hidden
1439 test that parent prevent a changeset to be hidden
1433
1440
1434 $ hg up 1 -q --hidden
1441 $ hg up 1 -q --hidden
1435 $ hg log --template='{rev}:{node}\n'
1442 $ hg log --template='{rev}:{node}\n'
1436 1:a765632148dc55d38c35c4f247c618701886cb2f
1443 1:a765632148dc55d38c35c4f247c618701886cb2f
1437 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1444 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1438
1445
1439 test that second parent prevent a changeset to be hidden too
1446 test that second parent prevent a changeset to be hidden too
1440
1447
1441 $ hg debugsetparents 0 1 # nothing suitable to merge here
1448 $ hg debugsetparents 0 1 # nothing suitable to merge here
1442 $ hg log --template='{rev}:{node}\n'
1449 $ hg log --template='{rev}:{node}\n'
1443 1:a765632148dc55d38c35c4f247c618701886cb2f
1450 1:a765632148dc55d38c35c4f247c618701886cb2f
1444 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1451 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1445 $ hg debugsetparents 1
1452 $ hg debugsetparents 1
1446 $ hg up -q null
1453 $ hg up -q null
1447
1454
1448 bookmarks prevent a changeset being hidden
1455 bookmarks prevent a changeset being hidden
1449
1456
1450 $ hg bookmark --hidden -r 1 X
1457 $ hg bookmark --hidden -r 1 X
1451 $ hg log --template '{rev}:{node}\n'
1458 $ hg log --template '{rev}:{node}\n'
1452 1:a765632148dc55d38c35c4f247c618701886cb2f
1459 1:a765632148dc55d38c35c4f247c618701886cb2f
1453 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1460 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1454 $ hg bookmark -d X
1461 $ hg bookmark -d X
1455
1462
1456 divergent bookmarks are not hidden
1463 divergent bookmarks are not hidden
1457
1464
1458 $ hg bookmark --hidden -r 1 X@foo
1465 $ hg bookmark --hidden -r 1 X@foo
1459 $ hg log --template '{rev}:{node}\n'
1466 $ hg log --template '{rev}:{node}\n'
1460 1:a765632148dc55d38c35c4f247c618701886cb2f
1467 1:a765632148dc55d38c35c4f247c618701886cb2f
1461 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1468 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1462
1469
1463 clear extensions configuration
1470 clear extensions configuration
1464 $ echo '[extensions]' >> $HGRCPATH
1471 $ echo '[extensions]' >> $HGRCPATH
1465 $ echo "obs=!" >> $HGRCPATH
1472 $ echo "obs=!" >> $HGRCPATH
1466 $ cd ..
1473 $ cd ..
1467
1474
1468 test -u/-k for problematic encoding
1475 test -u/-k for problematic encoding
1469 # unicode: cp932:
1476 # unicode: cp932:
1470 # u30A2 0x83 0x41(= 'A')
1477 # u30A2 0x83 0x41(= 'A')
1471 # u30C2 0x83 0x61(= 'a')
1478 # u30C2 0x83 0x61(= 'a')
1472
1479
1473 $ hg init problematicencoding
1480 $ hg init problematicencoding
1474 $ cd problematicencoding
1481 $ cd problematicencoding
1475
1482
1476 $ python > setup.sh <<EOF
1483 $ python > setup.sh <<EOF
1477 > print u'''
1484 > print u'''
1478 > echo a > text
1485 > echo a > text
1479 > hg add text
1486 > hg add text
1480 > hg --encoding utf-8 commit -u '\u30A2' -m none
1487 > hg --encoding utf-8 commit -u '\u30A2' -m none
1481 > echo b > text
1488 > echo b > text
1482 > hg --encoding utf-8 commit -u '\u30C2' -m none
1489 > hg --encoding utf-8 commit -u '\u30C2' -m none
1483 > echo c > text
1490 > echo c > text
1484 > hg --encoding utf-8 commit -u none -m '\u30A2'
1491 > hg --encoding utf-8 commit -u none -m '\u30A2'
1485 > echo d > text
1492 > echo d > text
1486 > hg --encoding utf-8 commit -u none -m '\u30C2'
1493 > hg --encoding utf-8 commit -u none -m '\u30C2'
1487 > '''.encode('utf-8')
1494 > '''.encode('utf-8')
1488 > EOF
1495 > EOF
1489 $ sh < setup.sh
1496 $ sh < setup.sh
1490
1497
1491 test in problematic encoding
1498 test in problematic encoding
1492 $ python > test.sh <<EOF
1499 $ python > test.sh <<EOF
1493 > print u'''
1500 > print u'''
1494 > hg --encoding cp932 log --template '{rev}\\n' -u '\u30A2'
1501 > hg --encoding cp932 log --template '{rev}\\n' -u '\u30A2'
1495 > echo ====
1502 > echo ====
1496 > hg --encoding cp932 log --template '{rev}\\n' -u '\u30C2'
1503 > hg --encoding cp932 log --template '{rev}\\n' -u '\u30C2'
1497 > echo ====
1504 > echo ====
1498 > hg --encoding cp932 log --template '{rev}\\n' -k '\u30A2'
1505 > hg --encoding cp932 log --template '{rev}\\n' -k '\u30A2'
1499 > echo ====
1506 > echo ====
1500 > hg --encoding cp932 log --template '{rev}\\n' -k '\u30C2'
1507 > hg --encoding cp932 log --template '{rev}\\n' -k '\u30C2'
1501 > '''.encode('cp932')
1508 > '''.encode('cp932')
1502 > EOF
1509 > EOF
1503 $ sh < test.sh
1510 $ sh < test.sh
1504 0
1511 0
1505 ====
1512 ====
1506 1
1513 1
1507 ====
1514 ====
1508 2
1515 2
1509 0
1516 0
1510 ====
1517 ====
1511 3
1518 3
1512 1
1519 1
1513
1520
1514 $ cd ..
1521 $ cd ..
1515
1522
1516 test hg log on non-existent files and on directories
1523 test hg log on non-existent files and on directories
1517 $ hg init issue1340
1524 $ hg init issue1340
1518 $ cd issue1340
1525 $ cd issue1340
1519 $ mkdir d1; mkdir D2; mkdir D3.i; mkdir d4.hg; mkdir d5.d; mkdir .d6
1526 $ mkdir d1; mkdir D2; mkdir D3.i; mkdir d4.hg; mkdir d5.d; mkdir .d6
1520 $ echo 1 > d1/f1
1527 $ echo 1 > d1/f1
1521 $ echo 1 > D2/f1
1528 $ echo 1 > D2/f1
1522 $ echo 1 > D3.i/f1
1529 $ echo 1 > D3.i/f1
1523 $ echo 1 > d4.hg/f1
1530 $ echo 1 > d4.hg/f1
1524 $ echo 1 > d5.d/f1
1531 $ echo 1 > d5.d/f1
1525 $ echo 1 > .d6/f1
1532 $ echo 1 > .d6/f1
1526 $ hg -q add .
1533 $ hg -q add .
1527 $ hg commit -m "a bunch of weird directories"
1534 $ hg commit -m "a bunch of weird directories"
1528 $ hg log -l1 d1/f1 | grep changeset
1535 $ hg log -l1 d1/f1 | grep changeset
1529 changeset: 0:65624cd9070a
1536 changeset: 0:65624cd9070a
1530 $ hg log -l1 f1
1537 $ hg log -l1 f1
1531 $ hg log -l1 . | grep changeset
1538 $ hg log -l1 . | grep changeset
1532 changeset: 0:65624cd9070a
1539 changeset: 0:65624cd9070a
1533 $ hg log -l1 ./ | grep changeset
1540 $ hg log -l1 ./ | grep changeset
1534 changeset: 0:65624cd9070a
1541 changeset: 0:65624cd9070a
1535 $ hg log -l1 d1 | grep changeset
1542 $ hg log -l1 d1 | grep changeset
1536 changeset: 0:65624cd9070a
1543 changeset: 0:65624cd9070a
1537 $ hg log -l1 D2 | grep changeset
1544 $ hg log -l1 D2 | grep changeset
1538 changeset: 0:65624cd9070a
1545 changeset: 0:65624cd9070a
1539 $ hg log -l1 D2/f1 | grep changeset
1546 $ hg log -l1 D2/f1 | grep changeset
1540 changeset: 0:65624cd9070a
1547 changeset: 0:65624cd9070a
1541 $ hg log -l1 D3.i | grep changeset
1548 $ hg log -l1 D3.i | grep changeset
1542 changeset: 0:65624cd9070a
1549 changeset: 0:65624cd9070a
1543 $ hg log -l1 D3.i/f1 | grep changeset
1550 $ hg log -l1 D3.i/f1 | grep changeset
1544 changeset: 0:65624cd9070a
1551 changeset: 0:65624cd9070a
1545 $ hg log -l1 d4.hg | grep changeset
1552 $ hg log -l1 d4.hg | grep changeset
1546 changeset: 0:65624cd9070a
1553 changeset: 0:65624cd9070a
1547 $ hg log -l1 d4.hg/f1 | grep changeset
1554 $ hg log -l1 d4.hg/f1 | grep changeset
1548 changeset: 0:65624cd9070a
1555 changeset: 0:65624cd9070a
1549 $ hg log -l1 d5.d | grep changeset
1556 $ hg log -l1 d5.d | grep changeset
1550 changeset: 0:65624cd9070a
1557 changeset: 0:65624cd9070a
1551 $ hg log -l1 d5.d/f1 | grep changeset
1558 $ hg log -l1 d5.d/f1 | grep changeset
1552 changeset: 0:65624cd9070a
1559 changeset: 0:65624cd9070a
1553 $ hg log -l1 .d6 | grep changeset
1560 $ hg log -l1 .d6 | grep changeset
1554 changeset: 0:65624cd9070a
1561 changeset: 0:65624cd9070a
1555 $ hg log -l1 .d6/f1 | grep changeset
1562 $ hg log -l1 .d6/f1 | grep changeset
1556 changeset: 0:65624cd9070a
1563 changeset: 0:65624cd9070a
1557
1564
1558 issue3772: hg log -r :null showing revision 0 as well
1565 issue3772: hg log -r :null showing revision 0 as well
1559
1566
1560 $ hg log -r :null
1567 $ hg log -r :null
1561 changeset: 0:65624cd9070a
1568 changeset: 0:65624cd9070a
1562 tag: tip
1569 tag: tip
1563 user: test
1570 user: test
1564 date: Thu Jan 01 00:00:00 1970 +0000
1571 date: Thu Jan 01 00:00:00 1970 +0000
1565 summary: a bunch of weird directories
1572 summary: a bunch of weird directories
1566
1573
1567 changeset: -1:000000000000
1574 changeset: -1:000000000000
1568 user:
1575 user:
1569 date: Thu Jan 01 00:00:00 1970 +0000
1576 date: Thu Jan 01 00:00:00 1970 +0000
1570
1577
1571 $ hg log -r null:null
1578 $ hg log -r null:null
1572 changeset: -1:000000000000
1579 changeset: -1:000000000000
1573 user:
1580 user:
1574 date: Thu Jan 01 00:00:00 1970 +0000
1581 date: Thu Jan 01 00:00:00 1970 +0000
1575
1582
1576 Check that adding an arbitrary name shows up in log automatically
1583 Check that adding an arbitrary name shows up in log automatically
1577
1584
1578 $ cat > ../names.py <<EOF
1585 $ cat > ../names.py <<EOF
1579 > """A small extension to test adding arbitrary names to a repo"""
1586 > """A small extension to test adding arbitrary names to a repo"""
1580 > from mercurial.namespaces import namespace
1587 > from mercurial.namespaces import namespace
1581 >
1588 >
1582 > def reposetup(ui, repo):
1589 > def reposetup(ui, repo):
1583 > foo = {'foo': repo[0].node()}
1590 > foo = {'foo': repo[0].node()}
1584 > names = lambda r: foo.keys()
1591 > names = lambda r: foo.keys()
1585 > namemap = lambda r, name: foo.get(name)
1592 > namemap = lambda r, name: foo.get(name)
1586 > nodemap = lambda r, node: [name for name, n in foo.iteritems()
1593 > nodemap = lambda r, node: [name for name, n in foo.iteritems()
1587 > if n == node]
1594 > if n == node]
1588 > ns = namespace("bars", templatename="bar", logname="barlog",
1595 > ns = namespace("bars", templatename="bar", logname="barlog",
1589 > colorname="barcolor", listnames=names, namemap=namemap,
1596 > colorname="barcolor", listnames=names, namemap=namemap,
1590 > nodemap=nodemap)
1597 > nodemap=nodemap)
1591 >
1598 >
1592 > repo.names.addnamespace(ns)
1599 > repo.names.addnamespace(ns)
1593 > EOF
1600 > EOF
1594
1601
1595 $ hg --config extensions.names=../names.py log -r 0
1602 $ hg --config extensions.names=../names.py log -r 0
1596 changeset: 0:65624cd9070a
1603 changeset: 0:65624cd9070a
1597 tag: tip
1604 tag: tip
1598 barlog: foo
1605 barlog: foo
1599 user: test
1606 user: test
1600 date: Thu Jan 01 00:00:00 1970 +0000
1607 date: Thu Jan 01 00:00:00 1970 +0000
1601 summary: a bunch of weird directories
1608 summary: a bunch of weird directories
1602
1609
1603 $ hg --config extensions.names=../names.py \
1610 $ hg --config extensions.names=../names.py \
1604 > --config extensions.color= --config color.log.barcolor=red \
1611 > --config extensions.color= --config color.log.barcolor=red \
1605 > --color=always log -r 0
1612 > --color=always log -r 0
1606 \x1b[0;33mchangeset: 0:65624cd9070a\x1b[0m (esc)
1613 \x1b[0;33mchangeset: 0:65624cd9070a\x1b[0m (esc)
1607 tag: tip
1614 tag: tip
1608 \x1b[0;31mbarlog: foo\x1b[0m (esc)
1615 \x1b[0;31mbarlog: foo\x1b[0m (esc)
1609 user: test
1616 user: test
1610 date: Thu Jan 01 00:00:00 1970 +0000
1617 date: Thu Jan 01 00:00:00 1970 +0000
1611 summary: a bunch of weird directories
1618 summary: a bunch of weird directories
1612
1619
1613 $ hg --config extensions.names=../names.py log -r 0 --template '{bars}\n'
1620 $ hg --config extensions.names=../names.py log -r 0 --template '{bars}\n'
1614 foo
1621 foo
1615
1622
1616 $ cd ..
1623 $ cd ..
1617
1624
1618 hg log -f dir across branches
1625 hg log -f dir across branches
1619
1626
1620 $ hg init acrossbranches
1627 $ hg init acrossbranches
1621 $ cd acrossbranches
1628 $ cd acrossbranches
1622 $ mkdir d
1629 $ mkdir d
1623 $ echo a > d/a && hg ci -Aqm a
1630 $ echo a > d/a && hg ci -Aqm a
1624 $ echo b > d/a && hg ci -Aqm b
1631 $ echo b > d/a && hg ci -Aqm b
1625 $ hg up -q 0
1632 $ hg up -q 0
1626 $ echo b > d/a && hg ci -Aqm c
1633 $ echo b > d/a && hg ci -Aqm c
1627 $ hg log -f d -T '{desc}' -G
1634 $ hg log -f d -T '{desc}' -G
1628 @ c
1635 @ c
1629 |
1636 |
1630 o a
1637 o a
1631
1638
1639 Ensure that largefiles doesn't intefere with following a normal file
1640 $ hg --config extensions.largefiles= log -f d -T '{desc}' -G
1641 @ c
1642 |
1643 o a
1644
1632 $ hg log -f d/a -T '{desc}' -G
1645 $ hg log -f d/a -T '{desc}' -G
1633 @ c
1646 @ c
1634 |
1647 |
1635 o a
1648 o a
1636
1649
1637 $ cd ..
1650 $ cd ..
1638
1651
1639 hg log -f with linkrev pointing to another branch
1652 hg log -f with linkrev pointing to another branch
1640 -------------------------------------------------
1653 -------------------------------------------------
1641
1654
1642 create history with a filerev whose linkrev points to another branch
1655 create history with a filerev whose linkrev points to another branch
1643
1656
1644 $ hg init branchedlinkrev
1657 $ hg init branchedlinkrev
1645 $ cd branchedlinkrev
1658 $ cd branchedlinkrev
1646 $ echo 1 > a
1659 $ echo 1 > a
1647 $ hg commit -Am 'content1'
1660 $ hg commit -Am 'content1'
1648 adding a
1661 adding a
1649 $ echo 2 > a
1662 $ echo 2 > a
1650 $ hg commit -m 'content2'
1663 $ hg commit -m 'content2'
1651 $ hg up --rev 'desc(content1)'
1664 $ hg up --rev 'desc(content1)'
1652 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1665 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1653 $ echo unrelated > unrelated
1666 $ echo unrelated > unrelated
1654 $ hg commit -Am 'unrelated'
1667 $ hg commit -Am 'unrelated'
1655 adding unrelated
1668 adding unrelated
1656 created new head
1669 created new head
1657 $ hg graft -r 'desc(content2)'
1670 $ hg graft -r 'desc(content2)'
1658 grafting 1:2294ae80ad84 "content2"
1671 grafting 1:2294ae80ad84 "content2"
1659 $ echo 3 > a
1672 $ echo 3 > a
1660 $ hg commit -m 'content3'
1673 $ hg commit -m 'content3'
1661 $ hg log -G
1674 $ hg log -G
1662 @ changeset: 4:50b9b36e9c5d
1675 @ changeset: 4:50b9b36e9c5d
1663 | tag: tip
1676 | tag: tip
1664 | user: test
1677 | user: test
1665 | date: Thu Jan 01 00:00:00 1970 +0000
1678 | date: Thu Jan 01 00:00:00 1970 +0000
1666 | summary: content3
1679 | summary: content3
1667 |
1680 |
1668 o changeset: 3:15b2327059e5
1681 o changeset: 3:15b2327059e5
1669 | user: test
1682 | user: test
1670 | date: Thu Jan 01 00:00:00 1970 +0000
1683 | date: Thu Jan 01 00:00:00 1970 +0000
1671 | summary: content2
1684 | summary: content2
1672 |
1685 |
1673 o changeset: 2:2029acd1168c
1686 o changeset: 2:2029acd1168c
1674 | parent: 0:ae0a3c9f9e95
1687 | parent: 0:ae0a3c9f9e95
1675 | user: test
1688 | user: test
1676 | date: Thu Jan 01 00:00:00 1970 +0000
1689 | date: Thu Jan 01 00:00:00 1970 +0000
1677 | summary: unrelated
1690 | summary: unrelated
1678 |
1691 |
1679 | o changeset: 1:2294ae80ad84
1692 | o changeset: 1:2294ae80ad84
1680 |/ user: test
1693 |/ user: test
1681 | date: Thu Jan 01 00:00:00 1970 +0000
1694 | date: Thu Jan 01 00:00:00 1970 +0000
1682 | summary: content2
1695 | summary: content2
1683 |
1696 |
1684 o changeset: 0:ae0a3c9f9e95
1697 o changeset: 0:ae0a3c9f9e95
1685 user: test
1698 user: test
1686 date: Thu Jan 01 00:00:00 1970 +0000
1699 date: Thu Jan 01 00:00:00 1970 +0000
1687 summary: content1
1700 summary: content1
1688
1701
1689
1702
1690 log -f on the file should list the graft result.
1703 log -f on the file should list the graft result.
1691
1704
1692 $ hg log -Gf a
1705 $ hg log -Gf a
1693 @ changeset: 4:50b9b36e9c5d
1706 @ changeset: 4:50b9b36e9c5d
1694 | tag: tip
1707 | tag: tip
1695 | user: test
1708 | user: test
1696 | date: Thu Jan 01 00:00:00 1970 +0000
1709 | date: Thu Jan 01 00:00:00 1970 +0000
1697 | summary: content3
1710 | summary: content3
1698 |
1711 |
1699 o changeset: 3:15b2327059e5
1712 o changeset: 3:15b2327059e5
1700 | user: test
1713 | user: test
1701 | date: Thu Jan 01 00:00:00 1970 +0000
1714 | date: Thu Jan 01 00:00:00 1970 +0000
1702 | summary: content2
1715 | summary: content2
1703 |
1716 |
1704 o changeset: 0:ae0a3c9f9e95
1717 o changeset: 0:ae0a3c9f9e95
1705 user: test
1718 user: test
1706 date: Thu Jan 01 00:00:00 1970 +0000
1719 date: Thu Jan 01 00:00:00 1970 +0000
1707 summary: content1
1720 summary: content1
1708
1721
1709
1722
1710 plain log lists the original version
1723 plain log lists the original version
1711 (XXX we should probably list both)
1724 (XXX we should probably list both)
1712
1725
1713 $ hg log -G a
1726 $ hg log -G a
1714 @ changeset: 4:50b9b36e9c5d
1727 @ changeset: 4:50b9b36e9c5d
1715 | tag: tip
1728 | tag: tip
1716 | user: test
1729 | user: test
1717 | date: Thu Jan 01 00:00:00 1970 +0000
1730 | date: Thu Jan 01 00:00:00 1970 +0000
1718 | summary: content3
1731 | summary: content3
1719 |
1732 |
1720 | o changeset: 1:2294ae80ad84
1733 | o changeset: 1:2294ae80ad84
1721 |/ user: test
1734 |/ user: test
1722 | date: Thu Jan 01 00:00:00 1970 +0000
1735 | date: Thu Jan 01 00:00:00 1970 +0000
1723 | summary: content2
1736 | summary: content2
1724 |
1737 |
1725 o changeset: 0:ae0a3c9f9e95
1738 o changeset: 0:ae0a3c9f9e95
1726 user: test
1739 user: test
1727 date: Thu Jan 01 00:00:00 1970 +0000
1740 date: Thu Jan 01 00:00:00 1970 +0000
1728 summary: content1
1741 summary: content1
1729
1742
1730
1743
1731 hg log -f from the grafted changeset
1744 hg log -f from the grafted changeset
1732 (The bootstrap should properly take the topology in account)
1745 (The bootstrap should properly take the topology in account)
1733
1746
1734 $ hg up 'desc(content3)^'
1747 $ hg up 'desc(content3)^'
1735 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1748 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1736 $ hg log -Gf a
1749 $ hg log -Gf a
1737 @ changeset: 3:15b2327059e5
1750 @ changeset: 3:15b2327059e5
1738 | user: test
1751 | user: test
1739 | date: Thu Jan 01 00:00:00 1970 +0000
1752 | date: Thu Jan 01 00:00:00 1970 +0000
1740 | summary: content2
1753 | summary: content2
1741 |
1754 |
1742 o changeset: 0:ae0a3c9f9e95
1755 o changeset: 0:ae0a3c9f9e95
1743 user: test
1756 user: test
1744 date: Thu Jan 01 00:00:00 1970 +0000
1757 date: Thu Jan 01 00:00:00 1970 +0000
1745 summary: content1
1758 summary: content1
1746
1759
1747
1760
1748 Test that we use the first non-hidden changeset in that case.
1761 Test that we use the first non-hidden changeset in that case.
1749
1762
1750 (hide the changeset)
1763 (hide the changeset)
1751
1764
1752 $ hg log -T '{node}\n' -r 1
1765 $ hg log -T '{node}\n' -r 1
1753 2294ae80ad8447bc78383182eeac50cb049df623
1766 2294ae80ad8447bc78383182eeac50cb049df623
1754 $ hg debugobsolete 2294ae80ad8447bc78383182eeac50cb049df623
1767 $ hg debugobsolete 2294ae80ad8447bc78383182eeac50cb049df623
1755 $ hg log -G
1768 $ hg log -G
1756 o changeset: 4:50b9b36e9c5d
1769 o changeset: 4:50b9b36e9c5d
1757 | tag: tip
1770 | tag: tip
1758 | user: test
1771 | user: test
1759 | date: Thu Jan 01 00:00:00 1970 +0000
1772 | date: Thu Jan 01 00:00:00 1970 +0000
1760 | summary: content3
1773 | summary: content3
1761 |
1774 |
1762 @ changeset: 3:15b2327059e5
1775 @ changeset: 3:15b2327059e5
1763 | user: test
1776 | user: test
1764 | date: Thu Jan 01 00:00:00 1970 +0000
1777 | date: Thu Jan 01 00:00:00 1970 +0000
1765 | summary: content2
1778 | summary: content2
1766 |
1779 |
1767 o changeset: 2:2029acd1168c
1780 o changeset: 2:2029acd1168c
1768 | parent: 0:ae0a3c9f9e95
1781 | parent: 0:ae0a3c9f9e95
1769 | user: test
1782 | user: test
1770 | date: Thu Jan 01 00:00:00 1970 +0000
1783 | date: Thu Jan 01 00:00:00 1970 +0000
1771 | summary: unrelated
1784 | summary: unrelated
1772 |
1785 |
1773 o changeset: 0:ae0a3c9f9e95
1786 o changeset: 0:ae0a3c9f9e95
1774 user: test
1787 user: test
1775 date: Thu Jan 01 00:00:00 1970 +0000
1788 date: Thu Jan 01 00:00:00 1970 +0000
1776 summary: content1
1789 summary: content1
1777
1790
1778
1791
1779 Check that log on the file does not drop the file revision.
1792 Check that log on the file does not drop the file revision.
1780
1793
1781 $ hg log -G a
1794 $ hg log -G a
1782 o changeset: 4:50b9b36e9c5d
1795 o changeset: 4:50b9b36e9c5d
1783 | tag: tip
1796 | tag: tip
1784 | user: test
1797 | user: test
1785 | date: Thu Jan 01 00:00:00 1970 +0000
1798 | date: Thu Jan 01 00:00:00 1970 +0000
1786 | summary: content3
1799 | summary: content3
1787 |
1800 |
1788 @ changeset: 3:15b2327059e5
1801 @ changeset: 3:15b2327059e5
1789 | user: test
1802 | user: test
1790 | date: Thu Jan 01 00:00:00 1970 +0000
1803 | date: Thu Jan 01 00:00:00 1970 +0000
1791 | summary: content2
1804 | summary: content2
1792 |
1805 |
1793 o changeset: 0:ae0a3c9f9e95
1806 o changeset: 0:ae0a3c9f9e95
1794 user: test
1807 user: test
1795 date: Thu Jan 01 00:00:00 1970 +0000
1808 date: Thu Jan 01 00:00:00 1970 +0000
1796 summary: content1
1809 summary: content1
1797
1810
1798
1811
1799 Even when a head revision is linkrev-shadowed.
1812 Even when a head revision is linkrev-shadowed.
1800
1813
1801 $ hg log -T '{node}\n' -r 4
1814 $ hg log -T '{node}\n' -r 4
1802 50b9b36e9c5df2c6fc6dcefa8ad0da929e84aed2
1815 50b9b36e9c5df2c6fc6dcefa8ad0da929e84aed2
1803 $ hg debugobsolete 50b9b36e9c5df2c6fc6dcefa8ad0da929e84aed2
1816 $ hg debugobsolete 50b9b36e9c5df2c6fc6dcefa8ad0da929e84aed2
1804 $ hg log -G a
1817 $ hg log -G a
1805 @ changeset: 3:15b2327059e5
1818 @ changeset: 3:15b2327059e5
1806 | tag: tip
1819 | tag: tip
1807 | user: test
1820 | user: test
1808 | date: Thu Jan 01 00:00:00 1970 +0000
1821 | date: Thu Jan 01 00:00:00 1970 +0000
1809 | summary: content2
1822 | summary: content2
1810 |
1823 |
1811 o changeset: 0:ae0a3c9f9e95
1824 o changeset: 0:ae0a3c9f9e95
1812 user: test
1825 user: test
1813 date: Thu Jan 01 00:00:00 1970 +0000
1826 date: Thu Jan 01 00:00:00 1970 +0000
1814 summary: content1
1827 summary: content1
1815
1828
1816
1829
1817 $ cd ..
1830 $ cd ..
1818
1831
1819 Even when the file revision is missing from some head:
1832 Even when the file revision is missing from some head:
1820
1833
1821 $ hg init issue4490
1834 $ hg init issue4490
1822 $ cd issue4490
1835 $ cd issue4490
1823 $ echo '[experimental]' >> .hg/hgrc
1836 $ echo '[experimental]' >> .hg/hgrc
1824 $ echo 'evolution=createmarkers' >> .hg/hgrc
1837 $ echo 'evolution=createmarkers' >> .hg/hgrc
1825 $ echo a > a
1838 $ echo a > a
1826 $ hg ci -Am0
1839 $ hg ci -Am0
1827 adding a
1840 adding a
1828 $ echo b > b
1841 $ echo b > b
1829 $ hg ci -Am1
1842 $ hg ci -Am1
1830 adding b
1843 adding b
1831 $ echo B > b
1844 $ echo B > b
1832 $ hg ci --amend -m 1
1845 $ hg ci --amend -m 1
1833 $ hg up 0
1846 $ hg up 0
1834 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1847 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1835 $ echo c > c
1848 $ echo c > c
1836 $ hg ci -Am2
1849 $ hg ci -Am2
1837 adding c
1850 adding c
1838 created new head
1851 created new head
1839 $ hg up 'head() and not .'
1852 $ hg up 'head() and not .'
1840 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1853 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1841 $ hg log -G
1854 $ hg log -G
1842 o changeset: 4:db815d6d32e6
1855 o changeset: 4:db815d6d32e6
1843 | tag: tip
1856 | tag: tip
1844 | parent: 0:f7b1eb17ad24
1857 | parent: 0:f7b1eb17ad24
1845 | user: test
1858 | user: test
1846 | date: Thu Jan 01 00:00:00 1970 +0000
1859 | date: Thu Jan 01 00:00:00 1970 +0000
1847 | summary: 2
1860 | summary: 2
1848 |
1861 |
1849 | @ changeset: 3:9bc8ce7f9356
1862 | @ changeset: 3:9bc8ce7f9356
1850 |/ parent: 0:f7b1eb17ad24
1863 |/ parent: 0:f7b1eb17ad24
1851 | user: test
1864 | user: test
1852 | date: Thu Jan 01 00:00:00 1970 +0000
1865 | date: Thu Jan 01 00:00:00 1970 +0000
1853 | summary: 1
1866 | summary: 1
1854 |
1867 |
1855 o changeset: 0:f7b1eb17ad24
1868 o changeset: 0:f7b1eb17ad24
1856 user: test
1869 user: test
1857 date: Thu Jan 01 00:00:00 1970 +0000
1870 date: Thu Jan 01 00:00:00 1970 +0000
1858 summary: 0
1871 summary: 0
1859
1872
1860 $ hg log -f -G b
1873 $ hg log -f -G b
1861 @ changeset: 3:9bc8ce7f9356
1874 @ changeset: 3:9bc8ce7f9356
1862 | parent: 0:f7b1eb17ad24
1875 | parent: 0:f7b1eb17ad24
1863 | user: test
1876 | user: test
1864 | date: Thu Jan 01 00:00:00 1970 +0000
1877 | date: Thu Jan 01 00:00:00 1970 +0000
1865 | summary: 1
1878 | summary: 1
1866 |
1879 |
1867 $ hg log -G b
1880 $ hg log -G b
1868 @ changeset: 3:9bc8ce7f9356
1881 @ changeset: 3:9bc8ce7f9356
1869 | parent: 0:f7b1eb17ad24
1882 | parent: 0:f7b1eb17ad24
1870 | user: test
1883 | user: test
1871 | date: Thu Jan 01 00:00:00 1970 +0000
1884 | date: Thu Jan 01 00:00:00 1970 +0000
1872 | summary: 1
1885 | summary: 1
1873 |
1886 |
1874 $ cd ..
1887 $ cd ..
1875
1888
1876 Check proper report when the manifest changes but not the file issue4499
1889 Check proper report when the manifest changes but not the file issue4499
1877 ------------------------------------------------------------------------
1890 ------------------------------------------------------------------------
1878
1891
1879 $ hg init issue4499
1892 $ hg init issue4499
1880 $ cd issue4499
1893 $ cd issue4499
1881 $ for f in A B C D F E G H I J K L M N O P Q R S T U; do
1894 $ for f in A B C D F E G H I J K L M N O P Q R S T U; do
1882 > echo 1 > $f;
1895 > echo 1 > $f;
1883 > hg add $f;
1896 > hg add $f;
1884 > done
1897 > done
1885 $ hg commit -m 'A1B1C1'
1898 $ hg commit -m 'A1B1C1'
1886 $ echo 2 > A
1899 $ echo 2 > A
1887 $ echo 2 > B
1900 $ echo 2 > B
1888 $ echo 2 > C
1901 $ echo 2 > C
1889 $ hg commit -m 'A2B2C2'
1902 $ hg commit -m 'A2B2C2'
1890 $ hg up 0
1903 $ hg up 0
1891 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
1904 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
1892 $ echo 3 > A
1905 $ echo 3 > A
1893 $ echo 2 > B
1906 $ echo 2 > B
1894 $ echo 2 > C
1907 $ echo 2 > C
1895 $ hg commit -m 'A3B2C2'
1908 $ hg commit -m 'A3B2C2'
1896 created new head
1909 created new head
1897
1910
1898 $ hg log -G
1911 $ hg log -G
1899 @ changeset: 2:fe5fc3d0eb17
1912 @ changeset: 2:fe5fc3d0eb17
1900 | tag: tip
1913 | tag: tip
1901 | parent: 0:abf4f0e38563
1914 | parent: 0:abf4f0e38563
1902 | user: test
1915 | user: test
1903 | date: Thu Jan 01 00:00:00 1970 +0000
1916 | date: Thu Jan 01 00:00:00 1970 +0000
1904 | summary: A3B2C2
1917 | summary: A3B2C2
1905 |
1918 |
1906 | o changeset: 1:07dcc6b312c0
1919 | o changeset: 1:07dcc6b312c0
1907 |/ user: test
1920 |/ user: test
1908 | date: Thu Jan 01 00:00:00 1970 +0000
1921 | date: Thu Jan 01 00:00:00 1970 +0000
1909 | summary: A2B2C2
1922 | summary: A2B2C2
1910 |
1923 |
1911 o changeset: 0:abf4f0e38563
1924 o changeset: 0:abf4f0e38563
1912 user: test
1925 user: test
1913 date: Thu Jan 01 00:00:00 1970 +0000
1926 date: Thu Jan 01 00:00:00 1970 +0000
1914 summary: A1B1C1
1927 summary: A1B1C1
1915
1928
1916
1929
1917 Log -f on B should reports current changesets
1930 Log -f on B should reports current changesets
1918
1931
1919 $ hg log -fG B
1932 $ hg log -fG B
1920 @ changeset: 2:fe5fc3d0eb17
1933 @ changeset: 2:fe5fc3d0eb17
1921 | tag: tip
1934 | tag: tip
1922 | parent: 0:abf4f0e38563
1935 | parent: 0:abf4f0e38563
1923 | user: test
1936 | user: test
1924 | date: Thu Jan 01 00:00:00 1970 +0000
1937 | date: Thu Jan 01 00:00:00 1970 +0000
1925 | summary: A3B2C2
1938 | summary: A3B2C2
1926 |
1939 |
1927 o changeset: 0:abf4f0e38563
1940 o changeset: 0:abf4f0e38563
1928 user: test
1941 user: test
1929 date: Thu Jan 01 00:00:00 1970 +0000
1942 date: Thu Jan 01 00:00:00 1970 +0000
1930 summary: A1B1C1
1943 summary: A1B1C1
1931
1944
1932 $ cd ..
1945 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now