##// END OF EJS Templates
largefiles: fix check-code errors.
Na'Tosha Bard -
r16248:51e6f318 default
parent child Browse files
Show More
@@ -1,968 +1,968 b''
1 # Copyright 2009-2010 Gregory P. Ward
1 # Copyright 2009-2010 Gregory P. Ward
2 # Copyright 2009-2010 Intelerad Medical Systems Incorporated
2 # Copyright 2009-2010 Intelerad Medical Systems Incorporated
3 # Copyright 2010-2011 Fog Creek Software
3 # Copyright 2010-2011 Fog Creek Software
4 # Copyright 2010-2011 Unity Technologies
4 # Copyright 2010-2011 Unity Technologies
5 #
5 #
6 # This software may be used and distributed according to the terms of the
6 # This software may be used and distributed according to the terms of the
7 # GNU General Public License version 2 or any later version.
7 # GNU General Public License version 2 or any later version.
8
8
9 '''Overridden Mercurial commands and functions for the largefiles extension'''
9 '''Overridden Mercurial commands and functions for the largefiles extension'''
10
10
11 import os
11 import os
12 import copy
12 import copy
13
13
14 from mercurial import hg, commands, util, cmdutil, scmutil, match as match_, \
14 from mercurial import hg, commands, util, cmdutil, scmutil, match as match_, \
15 node, archival, error, merge
15 node, archival, error, merge
16 from mercurial.i18n import _
16 from mercurial.i18n import _
17 from mercurial.node import hex
17 from mercurial.node import hex
18 from hgext import rebase
18 from hgext import rebase
19
19
20 import lfutil
20 import lfutil
21 import lfcommands
21 import lfcommands
22
22
23 # -- Utility functions: commonly/repeatedly needed functionality ---------------
23 # -- Utility functions: commonly/repeatedly needed functionality ---------------
24
24
25 def installnormalfilesmatchfn(manifest):
25 def installnormalfilesmatchfn(manifest):
26 '''overrides scmutil.match so that the matcher it returns will ignore all
26 '''overrides scmutil.match so that the matcher it returns will ignore all
27 largefiles'''
27 largefiles'''
28 oldmatch = None # for the closure
28 oldmatch = None # for the closure
29 def overridematch(ctx, pats=[], opts={}, globbed=False,
29 def overridematch(ctx, pats=[], opts={}, globbed=False,
30 default='relpath'):
30 default='relpath'):
31 match = oldmatch(ctx, pats, opts, globbed, default)
31 match = oldmatch(ctx, pats, opts, globbed, default)
32 m = copy.copy(match)
32 m = copy.copy(match)
33 notlfile = lambda f: not (lfutil.isstandin(f) or lfutil.standin(f) in
33 notlfile = lambda f: not (lfutil.isstandin(f) or lfutil.standin(f) in
34 manifest)
34 manifest)
35 m._files = filter(notlfile, m._files)
35 m._files = filter(notlfile, m._files)
36 m._fmap = set(m._files)
36 m._fmap = set(m._files)
37 origmatchfn = m.matchfn
37 origmatchfn = m.matchfn
38 m.matchfn = lambda f: notlfile(f) and origmatchfn(f) or None
38 m.matchfn = lambda f: notlfile(f) and origmatchfn(f) or None
39 return m
39 return m
40 oldmatch = installmatchfn(overridematch)
40 oldmatch = installmatchfn(overridematch)
41
41
42 def installmatchfn(f):
42 def installmatchfn(f):
43 oldmatch = scmutil.match
43 oldmatch = scmutil.match
44 setattr(f, 'oldmatch', oldmatch)
44 setattr(f, 'oldmatch', oldmatch)
45 scmutil.match = f
45 scmutil.match = f
46 return oldmatch
46 return oldmatch
47
47
48 def restorematchfn():
48 def restorematchfn():
49 '''restores scmutil.match to what it was before installnormalfilesmatchfn
49 '''restores scmutil.match to what it was before installnormalfilesmatchfn
50 was called. no-op if scmutil.match is its original function.
50 was called. no-op if scmutil.match is its original function.
51
51
52 Note that n calls to installnormalfilesmatchfn will require n calls to
52 Note that n calls to installnormalfilesmatchfn will require n calls to
53 restore matchfn to reverse'''
53 restore matchfn to reverse'''
54 scmutil.match = getattr(scmutil.match, 'oldmatch', scmutil.match)
54 scmutil.match = getattr(scmutil.match, 'oldmatch', scmutil.match)
55
55
56 def addlargefiles(ui, repo, *pats, **opts):
56 def addlargefiles(ui, repo, *pats, **opts):
57 large = opts.pop('large', None)
57 large = opts.pop('large', None)
58 lfsize = lfutil.getminsize(
58 lfsize = lfutil.getminsize(
59 ui, lfutil.islfilesrepo(repo), opts.pop('lfsize', None))
59 ui, lfutil.islfilesrepo(repo), opts.pop('lfsize', None))
60
60
61 lfmatcher = None
61 lfmatcher = None
62 if lfutil.islfilesrepo(repo):
62 if lfutil.islfilesrepo(repo):
63 lfpats = ui.configlist(lfutil.longname, 'patterns', default=[])
63 lfpats = ui.configlist(lfutil.longname, 'patterns', default=[])
64 if lfpats:
64 if lfpats:
65 lfmatcher = match_.match(repo.root, '', list(lfpats))
65 lfmatcher = match_.match(repo.root, '', list(lfpats))
66
66
67 lfnames = []
67 lfnames = []
68 m = scmutil.match(repo[None], pats, opts)
68 m = scmutil.match(repo[None], pats, opts)
69 m.bad = lambda x, y: None
69 m.bad = lambda x, y: None
70 wctx = repo[None]
70 wctx = repo[None]
71 for f in repo.walk(m):
71 for f in repo.walk(m):
72 exact = m.exact(f)
72 exact = m.exact(f)
73 lfile = lfutil.standin(f) in wctx
73 lfile = lfutil.standin(f) in wctx
74 nfile = f in wctx
74 nfile = f in wctx
75 exists = lfile or nfile
75 exists = lfile or nfile
76
76
77 # Don't warn the user when they attempt to add a normal tracked file.
77 # Don't warn the user when they attempt to add a normal tracked file.
78 # The normal add code will do that for us.
78 # The normal add code will do that for us.
79 if exact and exists:
79 if exact and exists:
80 if lfile:
80 if lfile:
81 ui.warn(_('%s already a largefile\n') % f)
81 ui.warn(_('%s already a largefile\n') % f)
82 continue
82 continue
83
83
84 if exact or not exists:
84 if exact or not exists:
85 abovemin = (lfsize and
85 abovemin = (lfsize and
86 os.lstat(repo.wjoin(f)).st_size >= lfsize * 1024 * 1024)
86 os.lstat(repo.wjoin(f)).st_size >= lfsize * 1024 * 1024)
87 if large or abovemin or (lfmatcher and lfmatcher(f)):
87 if large or abovemin or (lfmatcher and lfmatcher(f)):
88 lfnames.append(f)
88 lfnames.append(f)
89 if ui.verbose or not exact:
89 if ui.verbose or not exact:
90 ui.status(_('adding %s as a largefile\n') % m.rel(f))
90 ui.status(_('adding %s as a largefile\n') % m.rel(f))
91
91
92 bad = []
92 bad = []
93 standins = []
93 standins = []
94
94
95 # Need to lock, otherwise there could be a race condition between
95 # Need to lock, otherwise there could be a race condition between
96 # when standins are created and added to the repo.
96 # when standins are created and added to the repo.
97 wlock = repo.wlock()
97 wlock = repo.wlock()
98 try:
98 try:
99 if not opts.get('dry_run'):
99 if not opts.get('dry_run'):
100 lfdirstate = lfutil.openlfdirstate(ui, repo)
100 lfdirstate = lfutil.openlfdirstate(ui, repo)
101 for f in lfnames:
101 for f in lfnames:
102 standinname = lfutil.standin(f)
102 standinname = lfutil.standin(f)
103 lfutil.writestandin(repo, standinname, hash='',
103 lfutil.writestandin(repo, standinname, hash='',
104 executable=lfutil.getexecutable(repo.wjoin(f)))
104 executable=lfutil.getexecutable(repo.wjoin(f)))
105 standins.append(standinname)
105 standins.append(standinname)
106 if lfdirstate[f] == 'r':
106 if lfdirstate[f] == 'r':
107 lfdirstate.normallookup(f)
107 lfdirstate.normallookup(f)
108 else:
108 else:
109 lfdirstate.add(f)
109 lfdirstate.add(f)
110 lfdirstate.write()
110 lfdirstate.write()
111 bad += [lfutil.splitstandin(f)
111 bad += [lfutil.splitstandin(f)
112 for f in lfutil.repoadd(repo, standins)
112 for f in lfutil.repoadd(repo, standins)
113 if f in m.files()]
113 if f in m.files()]
114 finally:
114 finally:
115 wlock.release()
115 wlock.release()
116 return bad
116 return bad
117
117
118 def removelargefiles(ui, repo, *pats, **opts):
118 def removelargefiles(ui, repo, *pats, **opts):
119 after = opts.get('after')
119 after = opts.get('after')
120 if not pats and not after:
120 if not pats and not after:
121 raise util.Abort(_('no files specified'))
121 raise util.Abort(_('no files specified'))
122 m = scmutil.match(repo[None], pats, opts)
122 m = scmutil.match(repo[None], pats, opts)
123 try:
123 try:
124 repo.lfstatus = True
124 repo.lfstatus = True
125 s = repo.status(match=m, clean=True)
125 s = repo.status(match=m, clean=True)
126 finally:
126 finally:
127 repo.lfstatus = False
127 repo.lfstatus = False
128 manifest = repo[None].manifest()
128 manifest = repo[None].manifest()
129 modified, added, deleted, clean = [[f for f in list
129 modified, added, deleted, clean = [[f for f in list
130 if lfutil.standin(f) in manifest]
130 if lfutil.standin(f) in manifest]
131 for list in [s[0], s[1], s[3], s[6]]]
131 for list in [s[0], s[1], s[3], s[6]]]
132
132
133 def warn(files, reason):
133 def warn(files, reason):
134 for f in files:
134 for f in files:
135 ui.warn(_('not removing %s: %s (use forget to undo)\n')
135 ui.warn(_('not removing %s: %s (use forget to undo)\n')
136 % (m.rel(f), reason))
136 % (m.rel(f), reason))
137
137
138 if after:
138 if after:
139 remove, forget = deleted, []
139 remove, forget = deleted, []
140 warn(modified + added + clean, _('file still exists'))
140 warn(modified + added + clean, _('file still exists'))
141 else:
141 else:
142 remove, forget = deleted + clean, []
142 remove, forget = deleted + clean, []
143 warn(modified, _('file is modified'))
143 warn(modified, _('file is modified'))
144 warn(added, _('file has been marked for add'))
144 warn(added, _('file has been marked for add'))
145
145
146 for f in sorted(remove + forget):
146 for f in sorted(remove + forget):
147 if ui.verbose or not m.exact(f):
147 if ui.verbose or not m.exact(f):
148 ui.status(_('removing %s\n') % m.rel(f))
148 ui.status(_('removing %s\n') % m.rel(f))
149
149
150 # Need to lock because standin files are deleted then removed from the
150 # Need to lock because standin files are deleted then removed from the
151 # repository and we could race inbetween.
151 # repository and we could race inbetween.
152 wlock = repo.wlock()
152 wlock = repo.wlock()
153 try:
153 try:
154 lfdirstate = lfutil.openlfdirstate(ui, repo)
154 lfdirstate = lfutil.openlfdirstate(ui, repo)
155 for f in remove:
155 for f in remove:
156 if not after:
156 if not after:
157 # If this is being called by addremove, notify the user that we
157 # If this is being called by addremove, notify the user that we
158 # are removing the file.
158 # are removing the file.
159 if getattr(repo, "_isaddremove", False):
159 if getattr(repo, "_isaddremove", False):
160 ui.status(_('removing %s\n') % f)
160 ui.status(_('removing %s\n') % f)
161 if os.path.exists(repo.wjoin(f)):
161 if os.path.exists(repo.wjoin(f)):
162 util.unlinkpath(repo.wjoin(f))
162 util.unlinkpath(repo.wjoin(f))
163 lfdirstate.remove(f)
163 lfdirstate.remove(f)
164 lfdirstate.write()
164 lfdirstate.write()
165 forget = [lfutil.standin(f) for f in forget]
165 forget = [lfutil.standin(f) for f in forget]
166 remove = [lfutil.standin(f) for f in remove]
166 remove = [lfutil.standin(f) for f in remove]
167 lfutil.repoforget(repo, forget)
167 lfutil.repoforget(repo, forget)
168 # If this is being called by addremove, let the original addremove
168 # If this is being called by addremove, let the original addremove
169 # function handle this.
169 # function handle this.
170 if not getattr(repo, "_isaddremove", False):
170 if not getattr(repo, "_isaddremove", False):
171 lfutil.reporemove(repo, remove, unlink=True)
171 lfutil.reporemove(repo, remove, unlink=True)
172 finally:
172 finally:
173 wlock.release()
173 wlock.release()
174
174
175 # -- Wrappers: modify existing commands --------------------------------
175 # -- Wrappers: modify existing commands --------------------------------
176
176
177 # Add works by going through the files that the user wanted to add and
177 # Add works by going through the files that the user wanted to add and
178 # checking if they should be added as largefiles. Then it makes a new
178 # checking if they should be added as largefiles. Then it makes a new
179 # matcher which matches only the normal files and runs the original
179 # matcher which matches only the normal files and runs the original
180 # version of add.
180 # version of add.
181 def overrideadd(orig, ui, repo, *pats, **opts):
181 def overrideadd(orig, ui, repo, *pats, **opts):
182 normal = opts.pop('normal')
182 normal = opts.pop('normal')
183 if normal:
183 if normal:
184 if opts.get('large'):
184 if opts.get('large'):
185 raise util.Abort(_('--normal cannot be used with --large'))
185 raise util.Abort(_('--normal cannot be used with --large'))
186 return orig(ui, repo, *pats, **opts)
186 return orig(ui, repo, *pats, **opts)
187 bad = addlargefiles(ui, repo, *pats, **opts)
187 bad = addlargefiles(ui, repo, *pats, **opts)
188 installnormalfilesmatchfn(repo[None].manifest())
188 installnormalfilesmatchfn(repo[None].manifest())
189 result = orig(ui, repo, *pats, **opts)
189 result = orig(ui, repo, *pats, **opts)
190 restorematchfn()
190 restorematchfn()
191
191
192 return (result == 1 or bad) and 1 or 0
192 return (result == 1 or bad) and 1 or 0
193
193
194 def overrideremove(orig, ui, repo, *pats, **opts):
194 def overrideremove(orig, ui, repo, *pats, **opts):
195 installnormalfilesmatchfn(repo[None].manifest())
195 installnormalfilesmatchfn(repo[None].manifest())
196 orig(ui, repo, *pats, **opts)
196 orig(ui, repo, *pats, **opts)
197 restorematchfn()
197 restorematchfn()
198 removelargefiles(ui, repo, *pats, **opts)
198 removelargefiles(ui, repo, *pats, **opts)
199
199
200 def overridestatus(orig, ui, repo, *pats, **opts):
200 def overridestatus(orig, ui, repo, *pats, **opts):
201 try:
201 try:
202 repo.lfstatus = True
202 repo.lfstatus = True
203 return orig(ui, repo, *pats, **opts)
203 return orig(ui, repo, *pats, **opts)
204 finally:
204 finally:
205 repo.lfstatus = False
205 repo.lfstatus = False
206
206
207 def overridelog(orig, ui, repo, *pats, **opts):
207 def overridelog(orig, ui, repo, *pats, **opts):
208 try:
208 try:
209 repo.lfstatus = True
209 repo.lfstatus = True
210 orig(ui, repo, *pats, **opts)
210 orig(ui, repo, *pats, **opts)
211 finally:
211 finally:
212 repo.lfstatus = False
212 repo.lfstatus = False
213
213
214 def overrideverify(orig, ui, repo, *pats, **opts):
214 def overrideverify(orig, ui, repo, *pats, **opts):
215 large = opts.pop('large', False)
215 large = opts.pop('large', False)
216 all = opts.pop('lfa', False)
216 all = opts.pop('lfa', False)
217 contents = opts.pop('lfc', False)
217 contents = opts.pop('lfc', False)
218
218
219 result = orig(ui, repo, *pats, **opts)
219 result = orig(ui, repo, *pats, **opts)
220 if large:
220 if large:
221 result = result or lfcommands.verifylfiles(ui, repo, all, contents)
221 result = result or lfcommands.verifylfiles(ui, repo, all, contents)
222 return result
222 return result
223
223
224 # Override needs to refresh standins so that update's normal merge
224 # Override needs to refresh standins so that update's normal merge
225 # will go through properly. Then the other update hook (overriding repo.update)
225 # will go through properly. Then the other update hook (overriding repo.update)
226 # will get the new files. Filemerge is also overriden so that the merge
226 # will get the new files. Filemerge is also overriden so that the merge
227 # will merge standins correctly.
227 # will merge standins correctly.
228 def overrideupdate(orig, ui, repo, *pats, **opts):
228 def overrideupdate(orig, ui, repo, *pats, **opts):
229 lfdirstate = lfutil.openlfdirstate(ui, repo)
229 lfdirstate = lfutil.openlfdirstate(ui, repo)
230 s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
230 s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
231 False, False)
231 False, False)
232 (unsure, modified, added, removed, missing, unknown, ignored, clean) = s
232 (unsure, modified, added, removed, missing, unknown, ignored, clean) = s
233
233
234 # Need to lock between the standins getting updated and their
234 # Need to lock between the standins getting updated and their
235 # largefiles getting updated
235 # largefiles getting updated
236 wlock = repo.wlock()
236 wlock = repo.wlock()
237 try:
237 try:
238 if opts['check']:
238 if opts['check']:
239 mod = len(modified) > 0
239 mod = len(modified) > 0
240 for lfile in unsure:
240 for lfile in unsure:
241 standin = lfutil.standin(lfile)
241 standin = lfutil.standin(lfile)
242 if repo['.'][standin].data().strip() != \
242 if repo['.'][standin].data().strip() != \
243 lfutil.hashfile(repo.wjoin(lfile)):
243 lfutil.hashfile(repo.wjoin(lfile)):
244 mod = True
244 mod = True
245 else:
245 else:
246 lfdirstate.normal(lfile)
246 lfdirstate.normal(lfile)
247 lfdirstate.write()
247 lfdirstate.write()
248 if mod:
248 if mod:
249 raise util.Abort(_('uncommitted local changes'))
249 raise util.Abort(_('uncommitted local changes'))
250 # XXX handle removed differently
250 # XXX handle removed differently
251 if not opts['clean']:
251 if not opts['clean']:
252 for lfile in unsure + modified + added:
252 for lfile in unsure + modified + added:
253 lfutil.updatestandin(repo, lfutil.standin(lfile))
253 lfutil.updatestandin(repo, lfutil.standin(lfile))
254 finally:
254 finally:
255 wlock.release()
255 wlock.release()
256 return orig(ui, repo, *pats, **opts)
256 return orig(ui, repo, *pats, **opts)
257
257
258 # Before starting the manifest merge, merge.updates will call
258 # Before starting the manifest merge, merge.updates will call
259 # _checkunknown to check if there are any files in the merged-in
259 # _checkunknown to check if there are any files in the merged-in
260 # changeset that collide with unknown files in the working copy.
260 # changeset that collide with unknown files in the working copy.
261 #
261 #
262 # The largefiles are seen as unknown, so this prevents us from merging
262 # The largefiles are seen as unknown, so this prevents us from merging
263 # in a file 'foo' if we already have a largefile with the same name.
263 # in a file 'foo' if we already have a largefile with the same name.
264 #
264 #
265 # The overridden function filters the unknown files by removing any
265 # The overridden function filters the unknown files by removing any
266 # largefiles. This makes the merge proceed and we can then handle this
266 # largefiles. This makes the merge proceed and we can then handle this
267 # case further in the overridden manifestmerge function below.
267 # case further in the overridden manifestmerge function below.
268 def overridecheckunknownfile(origfn, repo, wctx, mctx, f):
268 def overridecheckunknownfile(origfn, repo, wctx, mctx, f):
269 if lfutil.standin(f) in wctx:
269 if lfutil.standin(f) in wctx:
270 return False
270 return False
271 return origfn(repo, wctx, mctx, f)
271 return origfn(repo, wctx, mctx, f)
272
272
273 # The manifest merge handles conflicts on the manifest level. We want
273 # The manifest merge handles conflicts on the manifest level. We want
274 # to handle changes in largefile-ness of files at this level too.
274 # to handle changes in largefile-ness of files at this level too.
275 #
275 #
276 # The strategy is to run the original manifestmerge and then process
276 # The strategy is to run the original manifestmerge and then process
277 # the action list it outputs. There are two cases we need to deal with:
277 # the action list it outputs. There are two cases we need to deal with:
278 #
278 #
279 # 1. Normal file in p1, largefile in p2. Here the largefile is
279 # 1. Normal file in p1, largefile in p2. Here the largefile is
280 # detected via its standin file, which will enter the working copy
280 # detected via its standin file, which will enter the working copy
281 # with a "get" action. It is not "merge" since the standin is all
281 # with a "get" action. It is not "merge" since the standin is all
282 # Mercurial is concerned with at this level -- the link to the
282 # Mercurial is concerned with at this level -- the link to the
283 # existing normal file is not relevant here.
283 # existing normal file is not relevant here.
284 #
284 #
285 # 2. Largefile in p1, normal file in p2. Here we get a "merge" action
285 # 2. Largefile in p1, normal file in p2. Here we get a "merge" action
286 # since the largefile will be present in the working copy and
286 # since the largefile will be present in the working copy and
287 # different from the normal file in p2. Mercurial therefore
287 # different from the normal file in p2. Mercurial therefore
288 # triggers a merge action.
288 # triggers a merge action.
289 #
289 #
290 # In both cases, we prompt the user and emit new actions to either
290 # In both cases, we prompt the user and emit new actions to either
291 # remove the standin (if the normal file was kept) or to remove the
291 # remove the standin (if the normal file was kept) or to remove the
292 # normal file and get the standin (if the largefile was kept). The
292 # normal file and get the standin (if the largefile was kept). The
293 # default prompt answer is to use the largefile version since it was
293 # default prompt answer is to use the largefile version since it was
294 # presumably changed on purpose.
294 # presumably changed on purpose.
295 #
295 #
296 # Finally, the merge.applyupdates function will then take care of
296 # Finally, the merge.applyupdates function will then take care of
297 # writing the files into the working copy and lfcommands.updatelfiles
297 # writing the files into the working copy and lfcommands.updatelfiles
298 # will update the largefiles.
298 # will update the largefiles.
299 def overridemanifestmerge(origfn, repo, p1, p2, pa, overwrite, partial):
299 def overridemanifestmerge(origfn, repo, p1, p2, pa, overwrite, partial):
300 actions = origfn(repo, p1, p2, pa, overwrite, partial)
300 actions = origfn(repo, p1, p2, pa, overwrite, partial)
301 processed = []
301 processed = []
302
302
303 for action in actions:
303 for action in actions:
304 if overwrite:
304 if overwrite:
305 processed.append(action)
305 processed.append(action)
306 continue
306 continue
307 f, m = action[:2]
307 f, m = action[:2]
308
308
309 choices = (_('&Largefile'), _('&Normal file'))
309 choices = (_('&Largefile'), _('&Normal file'))
310 if m == "g" and lfutil.splitstandin(f) in p1 and f in p2:
310 if m == "g" and lfutil.splitstandin(f) in p1 and f in p2:
311 # Case 1: normal file in the working copy, largefile in
311 # Case 1: normal file in the working copy, largefile in
312 # the second parent
312 # the second parent
313 lfile = lfutil.splitstandin(f)
313 lfile = lfutil.splitstandin(f)
314 standin = f
314 standin = f
315 msg = _('%s has been turned into a largefile\n'
315 msg = _('%s has been turned into a largefile\n'
316 'use (l)argefile or keep as (n)ormal file?') % lfile
316 'use (l)argefile or keep as (n)ormal file?') % lfile
317 if repo.ui.promptchoice(msg, choices, 0) == 0:
317 if repo.ui.promptchoice(msg, choices, 0) == 0:
318 processed.append((lfile, "r"))
318 processed.append((lfile, "r"))
319 processed.append((standin, "g", p2.flags(standin)))
319 processed.append((standin, "g", p2.flags(standin)))
320 else:
320 else:
321 processed.append((standin, "r"))
321 processed.append((standin, "r"))
322 elif m == "g" and lfutil.standin(f) in p1 and f in p2:
322 elif m == "g" and lfutil.standin(f) in p1 and f in p2:
323 # Case 2: largefile in the working copy, normal file in
323 # Case 2: largefile in the working copy, normal file in
324 # the second parent
324 # the second parent
325 standin = lfutil.standin(f)
325 standin = lfutil.standin(f)
326 lfile = f
326 lfile = f
327 msg = _('%s has been turned into a normal file\n'
327 msg = _('%s has been turned into a normal file\n'
328 'keep as (l)argefile or use (n)ormal file?') % lfile
328 'keep as (l)argefile or use (n)ormal file?') % lfile
329 if repo.ui.promptchoice(msg, choices, 0) == 0:
329 if repo.ui.promptchoice(msg, choices, 0) == 0:
330 processed.append((lfile, "r"))
330 processed.append((lfile, "r"))
331 else:
331 else:
332 processed.append((standin, "r"))
332 processed.append((standin, "r"))
333 processed.append((lfile, "g", p2.flags(lfile)))
333 processed.append((lfile, "g", p2.flags(lfile)))
334 else:
334 else:
335 processed.append(action)
335 processed.append(action)
336
336
337 return processed
337 return processed
338
338
339 # Override filemerge to prompt the user about how they wish to merge
339 # Override filemerge to prompt the user about how they wish to merge
340 # largefiles. This will handle identical edits, and copy/rename +
340 # largefiles. This will handle identical edits, and copy/rename +
341 # edit without prompting the user.
341 # edit without prompting the user.
342 def overridefilemerge(origfn, repo, mynode, orig, fcd, fco, fca):
342 def overridefilemerge(origfn, repo, mynode, orig, fcd, fco, fca):
343 # Use better variable names here. Because this is a wrapper we cannot
343 # Use better variable names here. Because this is a wrapper we cannot
344 # change the variable names in the function declaration.
344 # change the variable names in the function declaration.
345 fcdest, fcother, fcancestor = fcd, fco, fca
345 fcdest, fcother, fcancestor = fcd, fco, fca
346 if not lfutil.isstandin(orig):
346 if not lfutil.isstandin(orig):
347 return origfn(repo, mynode, orig, fcdest, fcother, fcancestor)
347 return origfn(repo, mynode, orig, fcdest, fcother, fcancestor)
348 else:
348 else:
349 if not fcother.cmp(fcdest): # files identical?
349 if not fcother.cmp(fcdest): # files identical?
350 return None
350 return None
351
351
352 # backwards, use working dir parent as ancestor
352 # backwards, use working dir parent as ancestor
353 if fcancestor == fcother:
353 if fcancestor == fcother:
354 fcancestor = fcdest.parents()[0]
354 fcancestor = fcdest.parents()[0]
355
355
356 if orig != fcother.path():
356 if orig != fcother.path():
357 repo.ui.status(_('merging %s and %s to %s\n')
357 repo.ui.status(_('merging %s and %s to %s\n')
358 % (lfutil.splitstandin(orig),
358 % (lfutil.splitstandin(orig),
359 lfutil.splitstandin(fcother.path()),
359 lfutil.splitstandin(fcother.path()),
360 lfutil.splitstandin(fcdest.path())))
360 lfutil.splitstandin(fcdest.path())))
361 else:
361 else:
362 repo.ui.status(_('merging %s\n')
362 repo.ui.status(_('merging %s\n')
363 % lfutil.splitstandin(fcdest.path()))
363 % lfutil.splitstandin(fcdest.path()))
364
364
365 if fcancestor.path() != fcother.path() and fcother.data() == \
365 if fcancestor.path() != fcother.path() and fcother.data() == \
366 fcancestor.data():
366 fcancestor.data():
367 return 0
367 return 0
368 if fcancestor.path() != fcdest.path() and fcdest.data() == \
368 if fcancestor.path() != fcdest.path() and fcdest.data() == \
369 fcancestor.data():
369 fcancestor.data():
370 repo.wwrite(fcdest.path(), fcother.data(), fcother.flags())
370 repo.wwrite(fcdest.path(), fcother.data(), fcother.flags())
371 return 0
371 return 0
372
372
373 if repo.ui.promptchoice(_('largefile %s has a merge conflict\n'
373 if repo.ui.promptchoice(_('largefile %s has a merge conflict\n'
374 'keep (l)ocal or take (o)ther?') %
374 'keep (l)ocal or take (o)ther?') %
375 lfutil.splitstandin(orig),
375 lfutil.splitstandin(orig),
376 (_('&Local'), _('&Other')), 0) == 0:
376 (_('&Local'), _('&Other')), 0) == 0:
377 return 0
377 return 0
378 else:
378 else:
379 repo.wwrite(fcdest.path(), fcother.data(), fcother.flags())
379 repo.wwrite(fcdest.path(), fcother.data(), fcother.flags())
380 return 0
380 return 0
381
381
382 # Copy first changes the matchers to match standins instead of
382 # Copy first changes the matchers to match standins instead of
383 # largefiles. Then it overrides util.copyfile in that function it
383 # largefiles. Then it overrides util.copyfile in that function it
384 # checks if the destination largefile already exists. It also keeps a
384 # checks if the destination largefile already exists. It also keeps a
385 # list of copied files so that the largefiles can be copied and the
385 # list of copied files so that the largefiles can be copied and the
386 # dirstate updated.
386 # dirstate updated.
387 def overridecopy(orig, ui, repo, pats, opts, rename=False):
387 def overridecopy(orig, ui, repo, pats, opts, rename=False):
388 # doesn't remove largefile on rename
388 # doesn't remove largefile on rename
389 if len(pats) < 2:
389 if len(pats) < 2:
390 # this isn't legal, let the original function deal with it
390 # this isn't legal, let the original function deal with it
391 return orig(ui, repo, pats, opts, rename)
391 return orig(ui, repo, pats, opts, rename)
392
392
393 def makestandin(relpath):
393 def makestandin(relpath):
394 path = scmutil.canonpath(repo.root, repo.getcwd(), relpath)
394 path = scmutil.canonpath(repo.root, repo.getcwd(), relpath)
395 return os.path.join(repo.wjoin(lfutil.standin(path)))
395 return os.path.join(repo.wjoin(lfutil.standin(path)))
396
396
397 fullpats = scmutil.expandpats(pats)
397 fullpats = scmutil.expandpats(pats)
398 dest = fullpats[-1]
398 dest = fullpats[-1]
399
399
400 if os.path.isdir(dest):
400 if os.path.isdir(dest):
401 if not os.path.isdir(makestandin(dest)):
401 if not os.path.isdir(makestandin(dest)):
402 os.makedirs(makestandin(dest))
402 os.makedirs(makestandin(dest))
403 # This could copy both lfiles and normal files in one command,
403 # This could copy both lfiles and normal files in one command,
404 # but we don't want to do that. First replace their matcher to
404 # but we don't want to do that. First replace their matcher to
405 # only match normal files and run it, then replace it to just
405 # only match normal files and run it, then replace it to just
406 # match largefiles and run it again.
406 # match largefiles and run it again.
407 nonormalfiles = False
407 nonormalfiles = False
408 nolfiles = False
408 nolfiles = False
409 try:
409 try:
410 try:
410 try:
411 installnormalfilesmatchfn(repo[None].manifest())
411 installnormalfilesmatchfn(repo[None].manifest())
412 result = orig(ui, repo, pats, opts, rename)
412 result = orig(ui, repo, pats, opts, rename)
413 except util.Abort, e:
413 except util.Abort, e:
414 if str(e) != 'no files to copy':
414 if str(e) != 'no files to copy':
415 raise e
415 raise e
416 else:
416 else:
417 nonormalfiles = True
417 nonormalfiles = True
418 result = 0
418 result = 0
419 finally:
419 finally:
420 restorematchfn()
420 restorematchfn()
421
421
422 # The first rename can cause our current working directory to be removed.
422 # The first rename can cause our current working directory to be removed.
423 # In that case there is nothing left to copy/rename so just quit.
423 # In that case there is nothing left to copy/rename so just quit.
424 try:
424 try:
425 repo.getcwd()
425 repo.getcwd()
426 except OSError:
426 except OSError:
427 return result
427 return result
428
428
429 try:
429 try:
430 try:
430 try:
431 # When we call orig below it creates the standins but we don't add them
431 # When we call orig below it creates the standins but we don't add
432 # to the dir state until later so lock during that time.
432 # them to the dir state until later so lock during that time.
433 wlock = repo.wlock()
433 wlock = repo.wlock()
434
434
435 manifest = repo[None].manifest()
435 manifest = repo[None].manifest()
436 oldmatch = None # for the closure
436 oldmatch = None # for the closure
437 def overridematch(ctx, pats=[], opts={}, globbed=False,
437 def overridematch(ctx, pats=[], opts={}, globbed=False,
438 default='relpath'):
438 default='relpath'):
439 newpats = []
439 newpats = []
440 # The patterns were previously mangled to add the standin
440 # The patterns were previously mangled to add the standin
441 # directory; we need to remove that now
441 # directory; we need to remove that now
442 for pat in pats:
442 for pat in pats:
443 if match_.patkind(pat) is None and lfutil.shortname in pat:
443 if match_.patkind(pat) is None and lfutil.shortname in pat:
444 newpats.append(pat.replace(lfutil.shortname, ''))
444 newpats.append(pat.replace(lfutil.shortname, ''))
445 else:
445 else:
446 newpats.append(pat)
446 newpats.append(pat)
447 match = oldmatch(ctx, newpats, opts, globbed, default)
447 match = oldmatch(ctx, newpats, opts, globbed, default)
448 m = copy.copy(match)
448 m = copy.copy(match)
449 lfile = lambda f: lfutil.standin(f) in manifest
449 lfile = lambda f: lfutil.standin(f) in manifest
450 m._files = [lfutil.standin(f) for f in m._files if lfile(f)]
450 m._files = [lfutil.standin(f) for f in m._files if lfile(f)]
451 m._fmap = set(m._files)
451 m._fmap = set(m._files)
452 origmatchfn = m.matchfn
452 origmatchfn = m.matchfn
453 m.matchfn = lambda f: (lfutil.isstandin(f) and
453 m.matchfn = lambda f: (lfutil.isstandin(f) and
454 (f in manifest) and
454 (f in manifest) and
455 origmatchfn(lfutil.splitstandin(f)) or
455 origmatchfn(lfutil.splitstandin(f)) or
456 None)
456 None)
457 return m
457 return m
458 oldmatch = installmatchfn(overridematch)
458 oldmatch = installmatchfn(overridematch)
459 listpats = []
459 listpats = []
460 for pat in pats:
460 for pat in pats:
461 if match_.patkind(pat) is not None:
461 if match_.patkind(pat) is not None:
462 listpats.append(pat)
462 listpats.append(pat)
463 else:
463 else:
464 listpats.append(makestandin(pat))
464 listpats.append(makestandin(pat))
465
465
466 try:
466 try:
467 origcopyfile = util.copyfile
467 origcopyfile = util.copyfile
468 copiedfiles = []
468 copiedfiles = []
469 def overridecopyfile(src, dest):
469 def overridecopyfile(src, dest):
470 if (lfutil.shortname in src and
470 if (lfutil.shortname in src and
471 dest.startswith(repo.wjoin(lfutil.shortname))):
471 dest.startswith(repo.wjoin(lfutil.shortname))):
472 destlfile = dest.replace(lfutil.shortname, '')
472 destlfile = dest.replace(lfutil.shortname, '')
473 if not opts['force'] and os.path.exists(destlfile):
473 if not opts['force'] and os.path.exists(destlfile):
474 raise IOError('',
474 raise IOError('',
475 _('destination largefile already exists'))
475 _('destination largefile already exists'))
476 copiedfiles.append((src, dest))
476 copiedfiles.append((src, dest))
477 origcopyfile(src, dest)
477 origcopyfile(src, dest)
478
478
479 util.copyfile = overridecopyfile
479 util.copyfile = overridecopyfile
480 result += orig(ui, repo, listpats, opts, rename)
480 result += orig(ui, repo, listpats, opts, rename)
481 finally:
481 finally:
482 util.copyfile = origcopyfile
482 util.copyfile = origcopyfile
483
483
484 lfdirstate = lfutil.openlfdirstate(ui, repo)
484 lfdirstate = lfutil.openlfdirstate(ui, repo)
485 for (src, dest) in copiedfiles:
485 for (src, dest) in copiedfiles:
486 if (lfutil.shortname in src and
486 if (lfutil.shortname in src and
487 dest.startswith(repo.wjoin(lfutil.shortname))):
487 dest.startswith(repo.wjoin(lfutil.shortname))):
488 srclfile = src.replace(repo.wjoin(lfutil.standin('')), '')
488 srclfile = src.replace(repo.wjoin(lfutil.standin('')), '')
489 destlfile = dest.replace(repo.wjoin(lfutil.standin('')), '')
489 destlfile = dest.replace(repo.wjoin(lfutil.standin('')), '')
490 destlfiledir = os.path.dirname(destlfile) or '.'
490 destlfiledir = os.path.dirname(destlfile) or '.'
491 if not os.path.isdir(destlfiledir):
491 if not os.path.isdir(destlfiledir):
492 os.makedirs(destlfiledir)
492 os.makedirs(destlfiledir)
493 if rename:
493 if rename:
494 os.rename(repo.wjoin(srclfile), repo.wjoin(destlfile))
494 os.rename(repo.wjoin(srclfile), repo.wjoin(destlfile))
495 lfdirstate.remove(srclfile)
495 lfdirstate.remove(srclfile)
496 else:
496 else:
497 util.copyfile(srclfile, destlfile)
497 util.copyfile(srclfile, destlfile)
498 lfdirstate.add(destlfile)
498 lfdirstate.add(destlfile)
499 lfdirstate.write()
499 lfdirstate.write()
500 except util.Abort, e:
500 except util.Abort, e:
501 if str(e) != 'no files to copy':
501 if str(e) != 'no files to copy':
502 raise e
502 raise e
503 else:
503 else:
504 nolfiles = True
504 nolfiles = True
505 finally:
505 finally:
506 restorematchfn()
506 restorematchfn()
507 wlock.release()
507 wlock.release()
508
508
509 if nolfiles and nonormalfiles:
509 if nolfiles and nonormalfiles:
510 raise util.Abort(_('no files to copy'))
510 raise util.Abort(_('no files to copy'))
511
511
512 return result
512 return result
513
513
514 # When the user calls revert, we have to be careful to not revert any
514 # When the user calls revert, we have to be careful to not revert any
515 # changes to other largefiles accidentally. This means we have to keep
515 # changes to other largefiles accidentally. This means we have to keep
516 # track of the largefiles that are being reverted so we only pull down
516 # track of the largefiles that are being reverted so we only pull down
517 # the necessary largefiles.
517 # the necessary largefiles.
518 #
518 #
519 # Standins are only updated (to match the hash of largefiles) before
519 # Standins are only updated (to match the hash of largefiles) before
520 # commits. Update the standins then run the original revert, changing
520 # commits. Update the standins then run the original revert, changing
521 # the matcher to hit standins instead of largefiles. Based on the
521 # the matcher to hit standins instead of largefiles. Based on the
522 # resulting standins update the largefiles. Then return the standins
522 # resulting standins update the largefiles. Then return the standins
523 # to their proper state
523 # to their proper state
524 def overriderevert(orig, ui, repo, *pats, **opts):
524 def overriderevert(orig, ui, repo, *pats, **opts):
525 # Because we put the standins in a bad state (by updating them)
525 # Because we put the standins in a bad state (by updating them)
526 # and then return them to a correct state we need to lock to
526 # and then return them to a correct state we need to lock to
527 # prevent others from changing them in their incorrect state.
527 # prevent others from changing them in their incorrect state.
528 wlock = repo.wlock()
528 wlock = repo.wlock()
529 try:
529 try:
530 lfdirstate = lfutil.openlfdirstate(ui, repo)
530 lfdirstate = lfutil.openlfdirstate(ui, repo)
531 (modified, added, removed, missing, unknown, ignored, clean) = \
531 (modified, added, removed, missing, unknown, ignored, clean) = \
532 lfutil.lfdirstatestatus(lfdirstate, repo, repo['.'].rev())
532 lfutil.lfdirstatestatus(lfdirstate, repo, repo['.'].rev())
533 for lfile in modified:
533 for lfile in modified:
534 lfutil.updatestandin(repo, lfutil.standin(lfile))
534 lfutil.updatestandin(repo, lfutil.standin(lfile))
535 for lfile in missing:
535 for lfile in missing:
536 os.unlink(repo.wjoin(lfutil.standin(lfile)))
536 os.unlink(repo.wjoin(lfutil.standin(lfile)))
537
537
538 try:
538 try:
539 ctx = repo[opts.get('rev')]
539 ctx = repo[opts.get('rev')]
540 oldmatch = None # for the closure
540 oldmatch = None # for the closure
541 def overridematch(ctx, pats=[], opts={}, globbed=False,
541 def overridematch(ctx, pats=[], opts={}, globbed=False,
542 default='relpath'):
542 default='relpath'):
543 match = oldmatch(ctx, pats, opts, globbed, default)
543 match = oldmatch(ctx, pats, opts, globbed, default)
544 m = copy.copy(match)
544 m = copy.copy(match)
545 def tostandin(f):
545 def tostandin(f):
546 if lfutil.standin(f) in ctx:
546 if lfutil.standin(f) in ctx:
547 return lfutil.standin(f)
547 return lfutil.standin(f)
548 elif lfutil.standin(f) in repo[None]:
548 elif lfutil.standin(f) in repo[None]:
549 return None
549 return None
550 return f
550 return f
551 m._files = [tostandin(f) for f in m._files]
551 m._files = [tostandin(f) for f in m._files]
552 m._files = [f for f in m._files if f is not None]
552 m._files = [f for f in m._files if f is not None]
553 m._fmap = set(m._files)
553 m._fmap = set(m._files)
554 origmatchfn = m.matchfn
554 origmatchfn = m.matchfn
555 def matchfn(f):
555 def matchfn(f):
556 if lfutil.isstandin(f):
556 if lfutil.isstandin(f):
557 # We need to keep track of what largefiles are being
557 # We need to keep track of what largefiles are being
558 # matched so we know which ones to update later --
558 # matched so we know which ones to update later --
559 # otherwise we accidentally revert changes to other
559 # otherwise we accidentally revert changes to other
560 # largefiles. This is repo-specific, so duckpunch the
560 # largefiles. This is repo-specific, so duckpunch the
561 # repo object to keep the list of largefiles for us
561 # repo object to keep the list of largefiles for us
562 # later.
562 # later.
563 if origmatchfn(lfutil.splitstandin(f)) and \
563 if origmatchfn(lfutil.splitstandin(f)) and \
564 (f in repo[None] or f in ctx):
564 (f in repo[None] or f in ctx):
565 lfileslist = getattr(repo, '_lfilestoupdate', [])
565 lfileslist = getattr(repo, '_lfilestoupdate', [])
566 lfileslist.append(lfutil.splitstandin(f))
566 lfileslist.append(lfutil.splitstandin(f))
567 repo._lfilestoupdate = lfileslist
567 repo._lfilestoupdate = lfileslist
568 return True
568 return True
569 else:
569 else:
570 return False
570 return False
571 return origmatchfn(f)
571 return origmatchfn(f)
572 m.matchfn = matchfn
572 m.matchfn = matchfn
573 return m
573 return m
574 oldmatch = installmatchfn(overridematch)
574 oldmatch = installmatchfn(overridematch)
575 scmutil.match
575 scmutil.match
576 matches = overridematch(repo[None], pats, opts)
576 matches = overridematch(repo[None], pats, opts)
577 orig(ui, repo, *pats, **opts)
577 orig(ui, repo, *pats, **opts)
578 finally:
578 finally:
579 restorematchfn()
579 restorematchfn()
580 lfileslist = getattr(repo, '_lfilestoupdate', [])
580 lfileslist = getattr(repo, '_lfilestoupdate', [])
581 lfcommands.updatelfiles(ui, repo, filelist=lfileslist,
581 lfcommands.updatelfiles(ui, repo, filelist=lfileslist,
582 printmessage=False)
582 printmessage=False)
583
583
584 # empty out the largefiles list so we start fresh next time
584 # empty out the largefiles list so we start fresh next time
585 repo._lfilestoupdate = []
585 repo._lfilestoupdate = []
586 for lfile in modified:
586 for lfile in modified:
587 if lfile in lfileslist:
587 if lfile in lfileslist:
588 if os.path.exists(repo.wjoin(lfutil.standin(lfile))) and lfile\
588 if os.path.exists(repo.wjoin(lfutil.standin(lfile))) and lfile\
589 in repo['.']:
589 in repo['.']:
590 lfutil.writestandin(repo, lfutil.standin(lfile),
590 lfutil.writestandin(repo, lfutil.standin(lfile),
591 repo['.'][lfile].data().strip(),
591 repo['.'][lfile].data().strip(),
592 'x' in repo['.'][lfile].flags())
592 'x' in repo['.'][lfile].flags())
593 lfdirstate = lfutil.openlfdirstate(ui, repo)
593 lfdirstate = lfutil.openlfdirstate(ui, repo)
594 for lfile in added:
594 for lfile in added:
595 standin = lfutil.standin(lfile)
595 standin = lfutil.standin(lfile)
596 if standin not in ctx and (standin in matches or opts.get('all')):
596 if standin not in ctx and (standin in matches or opts.get('all')):
597 if lfile in lfdirstate:
597 if lfile in lfdirstate:
598 lfdirstate.drop(lfile)
598 lfdirstate.drop(lfile)
599 util.unlinkpath(repo.wjoin(standin))
599 util.unlinkpath(repo.wjoin(standin))
600 lfdirstate.write()
600 lfdirstate.write()
601 finally:
601 finally:
602 wlock.release()
602 wlock.release()
603
603
604 def hgupdate(orig, repo, node):
604 def hgupdate(orig, repo, node):
605 # Only call updatelfiles the standins that have changed to save time
605 # Only call updatelfiles the standins that have changed to save time
606 oldstandins = lfutil.getstandinsstate(repo)
606 oldstandins = lfutil.getstandinsstate(repo)
607 result = orig(repo, node)
607 result = orig(repo, node)
608 newstandins = lfutil.getstandinsstate(repo)
608 newstandins = lfutil.getstandinsstate(repo)
609 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
609 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
610 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist, printmessage=True)
610 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist, printmessage=True)
611 return result
611 return result
612
612
613 def hgclean(orig, repo, node, show_stats=True):
613 def hgclean(orig, repo, node, show_stats=True):
614 result = orig(repo, node, show_stats)
614 result = orig(repo, node, show_stats)
615 lfcommands.updatelfiles(repo.ui, repo)
615 lfcommands.updatelfiles(repo.ui, repo)
616 return result
616 return result
617
617
618 def hgmerge(orig, repo, node, force=None, remind=True):
618 def hgmerge(orig, repo, node, force=None, remind=True):
619 # Mark the repo as being in the middle of a merge, so that
619 # Mark the repo as being in the middle of a merge, so that
620 # updatelfiles() will know that it needs to trust the standins in
620 # updatelfiles() will know that it needs to trust the standins in
621 # the working copy, not in the standins in the current node
621 # the working copy, not in the standins in the current node
622 repo._ismerging = True
622 repo._ismerging = True
623 try:
623 try:
624 result = orig(repo, node, force, remind)
624 result = orig(repo, node, force, remind)
625 lfcommands.updatelfiles(repo.ui, repo)
625 lfcommands.updatelfiles(repo.ui, repo)
626 finally:
626 finally:
627 repo._ismerging = False
627 repo._ismerging = False
628 return result
628 return result
629
629
630 # When we rebase a repository with remotely changed largefiles, we need to
630 # When we rebase a repository with remotely changed largefiles, we need to
631 # take some extra care so that the largefiles are correctly updated in the
631 # take some extra care so that the largefiles are correctly updated in the
632 # working copy
632 # working copy
633 def overridepull(orig, ui, repo, source=None, **opts):
633 def overridepull(orig, ui, repo, source=None, **opts):
634 if opts.get('rebase', False):
634 if opts.get('rebase', False):
635 repo._isrebasing = True
635 repo._isrebasing = True
636 try:
636 try:
637 if opts.get('update'):
637 if opts.get('update'):
638 del opts['update']
638 del opts['update']
639 ui.debug('--update and --rebase are not compatible, ignoring '
639 ui.debug('--update and --rebase are not compatible, ignoring '
640 'the update flag\n')
640 'the update flag\n')
641 del opts['rebase']
641 del opts['rebase']
642 cmdutil.bailifchanged(repo)
642 cmdutil.bailifchanged(repo)
643 revsprepull = len(repo)
643 revsprepull = len(repo)
644 origpostincoming = commands.postincoming
644 origpostincoming = commands.postincoming
645 def _dummy(*args, **kwargs):
645 def _dummy(*args, **kwargs):
646 pass
646 pass
647 commands.postincoming = _dummy
647 commands.postincoming = _dummy
648 repo.lfpullsource = source
648 repo.lfpullsource = source
649 if not source:
649 if not source:
650 source = 'default'
650 source = 'default'
651 try:
651 try:
652 result = commands.pull(ui, repo, source, **opts)
652 result = commands.pull(ui, repo, source, **opts)
653 finally:
653 finally:
654 commands.postincoming = origpostincoming
654 commands.postincoming = origpostincoming
655 revspostpull = len(repo)
655 revspostpull = len(repo)
656 if revspostpull > revsprepull:
656 if revspostpull > revsprepull:
657 result = result or rebase.rebase(ui, repo)
657 result = result or rebase.rebase(ui, repo)
658 finally:
658 finally:
659 repo._isrebasing = False
659 repo._isrebasing = False
660 else:
660 else:
661 repo.lfpullsource = source
661 repo.lfpullsource = source
662 if not source:
662 if not source:
663 source = 'default'
663 source = 'default'
664 oldheads = lfutil.getcurrentheads(repo)
664 oldheads = lfutil.getcurrentheads(repo)
665 result = orig(ui, repo, source, **opts)
665 result = orig(ui, repo, source, **opts)
666 # If we do not have the new largefiles for any new heads we pulled, we
666 # If we do not have the new largefiles for any new heads we pulled, we
667 # will run into a problem later if we try to merge or rebase with one of
667 # will run into a problem later if we try to merge or rebase with one of
668 # these heads, so cache the largefiles now direclty into the system
668 # these heads, so cache the largefiles now direclty into the system
669 # cache.
669 # cache.
670 ui.status(_("caching new largefiles\n"))
670 ui.status(_("caching new largefiles\n"))
671 numcached = 0
671 numcached = 0
672 heads = lfutil.getcurrentheads(repo)
672 heads = lfutil.getcurrentheads(repo)
673 newheads = set(heads).difference(set(oldheads))
673 newheads = set(heads).difference(set(oldheads))
674 for head in newheads:
674 for head in newheads:
675 (cached, missing) = lfcommands.cachelfiles(ui, repo, head)
675 (cached, missing) = lfcommands.cachelfiles(ui, repo, head)
676 numcached += len(cached)
676 numcached += len(cached)
677 ui.status(_("%d largefiles cached\n") % numcached)
677 ui.status(_("%d largefiles cached\n") % numcached)
678 return result
678 return result
679
679
680 def overriderebase(orig, ui, repo, **opts):
680 def overriderebase(orig, ui, repo, **opts):
681 repo._isrebasing = True
681 repo._isrebasing = True
682 try:
682 try:
683 orig(ui, repo, **opts)
683 orig(ui, repo, **opts)
684 finally:
684 finally:
685 repo._isrebasing = False
685 repo._isrebasing = False
686
686
687 def overridearchive(orig, repo, dest, node, kind, decode=True, matchfn=None,
687 def overridearchive(orig, repo, dest, node, kind, decode=True, matchfn=None,
688 prefix=None, mtime=None, subrepos=None):
688 prefix=None, mtime=None, subrepos=None):
689 # No need to lock because we are only reading history and
689 # No need to lock because we are only reading history and
690 # largefile caches, neither of which are modified.
690 # largefile caches, neither of which are modified.
691 lfcommands.cachelfiles(repo.ui, repo, node)
691 lfcommands.cachelfiles(repo.ui, repo, node)
692
692
693 if kind not in archival.archivers:
693 if kind not in archival.archivers:
694 raise util.Abort(_("unknown archive type '%s'") % kind)
694 raise util.Abort(_("unknown archive type '%s'") % kind)
695
695
696 ctx = repo[node]
696 ctx = repo[node]
697
697
698 if kind == 'files':
698 if kind == 'files':
699 if prefix:
699 if prefix:
700 raise util.Abort(
700 raise util.Abort(
701 _('cannot give prefix when archiving to files'))
701 _('cannot give prefix when archiving to files'))
702 else:
702 else:
703 prefix = archival.tidyprefix(dest, kind, prefix)
703 prefix = archival.tidyprefix(dest, kind, prefix)
704
704
705 def write(name, mode, islink, getdata):
705 def write(name, mode, islink, getdata):
706 if matchfn and not matchfn(name):
706 if matchfn and not matchfn(name):
707 return
707 return
708 data = getdata()
708 data = getdata()
709 if decode:
709 if decode:
710 data = repo.wwritedata(name, data)
710 data = repo.wwritedata(name, data)
711 archiver.addfile(prefix + name, mode, islink, data)
711 archiver.addfile(prefix + name, mode, islink, data)
712
712
713 archiver = archival.archivers[kind](dest, mtime or ctx.date()[0])
713 archiver = archival.archivers[kind](dest, mtime or ctx.date()[0])
714
714
715 if repo.ui.configbool("ui", "archivemeta", True):
715 if repo.ui.configbool("ui", "archivemeta", True):
716 def metadata():
716 def metadata():
717 base = 'repo: %s\nnode: %s\nbranch: %s\n' % (
717 base = 'repo: %s\nnode: %s\nbranch: %s\n' % (
718 hex(repo.changelog.node(0)), hex(node), ctx.branch())
718 hex(repo.changelog.node(0)), hex(node), ctx.branch())
719
719
720 tags = ''.join('tag: %s\n' % t for t in ctx.tags()
720 tags = ''.join('tag: %s\n' % t for t in ctx.tags()
721 if repo.tagtype(t) == 'global')
721 if repo.tagtype(t) == 'global')
722 if not tags:
722 if not tags:
723 repo.ui.pushbuffer()
723 repo.ui.pushbuffer()
724 opts = {'template': '{latesttag}\n{latesttagdistance}',
724 opts = {'template': '{latesttag}\n{latesttagdistance}',
725 'style': '', 'patch': None, 'git': None}
725 'style': '', 'patch': None, 'git': None}
726 cmdutil.show_changeset(repo.ui, repo, opts).show(ctx)
726 cmdutil.show_changeset(repo.ui, repo, opts).show(ctx)
727 ltags, dist = repo.ui.popbuffer().split('\n')
727 ltags, dist = repo.ui.popbuffer().split('\n')
728 tags = ''.join('latesttag: %s\n' % t for t in ltags.split(':'))
728 tags = ''.join('latesttag: %s\n' % t for t in ltags.split(':'))
729 tags += 'latesttagdistance: %s\n' % dist
729 tags += 'latesttagdistance: %s\n' % dist
730
730
731 return base + tags
731 return base + tags
732
732
733 write('.hg_archival.txt', 0644, False, metadata)
733 write('.hg_archival.txt', 0644, False, metadata)
734
734
735 for f in ctx:
735 for f in ctx:
736 ff = ctx.flags(f)
736 ff = ctx.flags(f)
737 getdata = ctx[f].data
737 getdata = ctx[f].data
738 if lfutil.isstandin(f):
738 if lfutil.isstandin(f):
739 path = lfutil.findfile(repo, getdata().strip())
739 path = lfutil.findfile(repo, getdata().strip())
740 if path is None:
740 if path is None:
741 raise util.Abort(
741 raise util.Abort(
742 _('largefile %s not found in repo store or system cache')
742 _('largefile %s not found in repo store or system cache')
743 % lfutil.splitstandin(f))
743 % lfutil.splitstandin(f))
744 f = lfutil.splitstandin(f)
744 f = lfutil.splitstandin(f)
745
745
746 def getdatafn():
746 def getdatafn():
747 fd = None
747 fd = None
748 try:
748 try:
749 fd = open(path, 'rb')
749 fd = open(path, 'rb')
750 return fd.read()
750 return fd.read()
751 finally:
751 finally:
752 if fd:
752 if fd:
753 fd.close()
753 fd.close()
754
754
755 getdata = getdatafn
755 getdata = getdatafn
756 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
756 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
757
757
758 if subrepos:
758 if subrepos:
759 for subpath in ctx.substate:
759 for subpath in ctx.substate:
760 sub = ctx.sub(subpath)
760 sub = ctx.sub(subpath)
761 sub.archive(repo.ui, archiver, prefix)
761 sub.archive(repo.ui, archiver, prefix)
762
762
763 archiver.done()
763 archiver.done()
764
764
765 # If a largefile is modified, the change is not reflected in its
765 # If a largefile is modified, the change is not reflected in its
766 # standin until a commit. cmdutil.bailifchanged() raises an exception
766 # standin until a commit. cmdutil.bailifchanged() raises an exception
767 # if the repo has uncommitted changes. Wrap it to also check if
767 # if the repo has uncommitted changes. Wrap it to also check if
768 # largefiles were changed. This is used by bisect and backout.
768 # largefiles were changed. This is used by bisect and backout.
769 def overridebailifchanged(orig, repo):
769 def overridebailifchanged(orig, repo):
770 orig(repo)
770 orig(repo)
771 repo.lfstatus = True
771 repo.lfstatus = True
772 modified, added, removed, deleted = repo.status()[:4]
772 modified, added, removed, deleted = repo.status()[:4]
773 repo.lfstatus = False
773 repo.lfstatus = False
774 if modified or added or removed or deleted:
774 if modified or added or removed or deleted:
775 raise util.Abort(_('outstanding uncommitted changes'))
775 raise util.Abort(_('outstanding uncommitted changes'))
776
776
777 # Fetch doesn't use cmdutil.bailifchanged so override it to add the check
777 # Fetch doesn't use cmdutil.bailifchanged so override it to add the check
778 def overridefetch(orig, ui, repo, *pats, **opts):
778 def overridefetch(orig, ui, repo, *pats, **opts):
779 repo.lfstatus = True
779 repo.lfstatus = True
780 modified, added, removed, deleted = repo.status()[:4]
780 modified, added, removed, deleted = repo.status()[:4]
781 repo.lfstatus = False
781 repo.lfstatus = False
782 if modified or added or removed or deleted:
782 if modified or added or removed or deleted:
783 raise util.Abort(_('outstanding uncommitted changes'))
783 raise util.Abort(_('outstanding uncommitted changes'))
784 return orig(ui, repo, *pats, **opts)
784 return orig(ui, repo, *pats, **opts)
785
785
786 def overrideforget(orig, ui, repo, *pats, **opts):
786 def overrideforget(orig, ui, repo, *pats, **opts):
787 installnormalfilesmatchfn(repo[None].manifest())
787 installnormalfilesmatchfn(repo[None].manifest())
788 orig(ui, repo, *pats, **opts)
788 orig(ui, repo, *pats, **opts)
789 restorematchfn()
789 restorematchfn()
790 m = scmutil.match(repo[None], pats, opts)
790 m = scmutil.match(repo[None], pats, opts)
791
791
792 try:
792 try:
793 repo.lfstatus = True
793 repo.lfstatus = True
794 s = repo.status(match=m, clean=True)
794 s = repo.status(match=m, clean=True)
795 finally:
795 finally:
796 repo.lfstatus = False
796 repo.lfstatus = False
797 forget = sorted(s[0] + s[1] + s[3] + s[6])
797 forget = sorted(s[0] + s[1] + s[3] + s[6])
798 forget = [f for f in forget if lfutil.standin(f) in repo[None].manifest()]
798 forget = [f for f in forget if lfutil.standin(f) in repo[None].manifest()]
799
799
800 for f in forget:
800 for f in forget:
801 if lfutil.standin(f) not in repo.dirstate and not \
801 if lfutil.standin(f) not in repo.dirstate and not \
802 os.path.isdir(m.rel(lfutil.standin(f))):
802 os.path.isdir(m.rel(lfutil.standin(f))):
803 ui.warn(_('not removing %s: file is already untracked\n')
803 ui.warn(_('not removing %s: file is already untracked\n')
804 % m.rel(f))
804 % m.rel(f))
805
805
806 for f in forget:
806 for f in forget:
807 if ui.verbose or not m.exact(f):
807 if ui.verbose or not m.exact(f):
808 ui.status(_('removing %s\n') % m.rel(f))
808 ui.status(_('removing %s\n') % m.rel(f))
809
809
810 # Need to lock because standin files are deleted then removed from the
810 # Need to lock because standin files are deleted then removed from the
811 # repository and we could race inbetween.
811 # repository and we could race inbetween.
812 wlock = repo.wlock()
812 wlock = repo.wlock()
813 try:
813 try:
814 lfdirstate = lfutil.openlfdirstate(ui, repo)
814 lfdirstate = lfutil.openlfdirstate(ui, repo)
815 for f in forget:
815 for f in forget:
816 if lfdirstate[f] == 'a':
816 if lfdirstate[f] == 'a':
817 lfdirstate.drop(f)
817 lfdirstate.drop(f)
818 else:
818 else:
819 lfdirstate.remove(f)
819 lfdirstate.remove(f)
820 lfdirstate.write()
820 lfdirstate.write()
821 lfutil.reporemove(repo, [lfutil.standin(f) for f in forget],
821 lfutil.reporemove(repo, [lfutil.standin(f) for f in forget],
822 unlink=True)
822 unlink=True)
823 finally:
823 finally:
824 wlock.release()
824 wlock.release()
825
825
826 def getoutgoinglfiles(ui, repo, dest=None, **opts):
826 def getoutgoinglfiles(ui, repo, dest=None, **opts):
827 dest = ui.expandpath(dest or 'default-push', dest or 'default')
827 dest = ui.expandpath(dest or 'default-push', dest or 'default')
828 dest, branches = hg.parseurl(dest, opts.get('branch'))
828 dest, branches = hg.parseurl(dest, opts.get('branch'))
829 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
829 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
830 if revs:
830 if revs:
831 revs = [repo.lookup(rev) for rev in revs]
831 revs = [repo.lookup(rev) for rev in revs]
832
832
833 remoteui = hg.remoteui
833 remoteui = hg.remoteui
834
834
835 try:
835 try:
836 remote = hg.repository(remoteui(repo, opts), dest)
836 remote = hg.repository(remoteui(repo, opts), dest)
837 except error.RepoError:
837 except error.RepoError:
838 return None
838 return None
839 o = lfutil.findoutgoing(repo, remote, False)
839 o = lfutil.findoutgoing(repo, remote, False)
840 if not o:
840 if not o:
841 return None
841 return None
842 o = repo.changelog.nodesbetween(o, revs)[0]
842 o = repo.changelog.nodesbetween(o, revs)[0]
843 if opts.get('newest_first'):
843 if opts.get('newest_first'):
844 o.reverse()
844 o.reverse()
845
845
846 toupload = set()
846 toupload = set()
847 for n in o:
847 for n in o:
848 parents = [p for p in repo.changelog.parents(n) if p != node.nullid]
848 parents = [p for p in repo.changelog.parents(n) if p != node.nullid]
849 ctx = repo[n]
849 ctx = repo[n]
850 files = set(ctx.files())
850 files = set(ctx.files())
851 if len(parents) == 2:
851 if len(parents) == 2:
852 mc = ctx.manifest()
852 mc = ctx.manifest()
853 mp1 = ctx.parents()[0].manifest()
853 mp1 = ctx.parents()[0].manifest()
854 mp2 = ctx.parents()[1].manifest()
854 mp2 = ctx.parents()[1].manifest()
855 for f in mp1:
855 for f in mp1:
856 if f not in mc:
856 if f not in mc:
857 files.add(f)
857 files.add(f)
858 for f in mp2:
858 for f in mp2:
859 if f not in mc:
859 if f not in mc:
860 files.add(f)
860 files.add(f)
861 for f in mc:
861 for f in mc:
862 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
862 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
863 files.add(f)
863 files.add(f)
864 toupload = toupload.union(
864 toupload = toupload.union(
865 set([f for f in files if lfutil.isstandin(f) and f in ctx]))
865 set([f for f in files if lfutil.isstandin(f) and f in ctx]))
866 return toupload
866 return toupload
867
867
868 def overrideoutgoing(orig, ui, repo, dest=None, **opts):
868 def overrideoutgoing(orig, ui, repo, dest=None, **opts):
869 orig(ui, repo, dest, **opts)
869 orig(ui, repo, dest, **opts)
870
870
871 if opts.pop('large', None):
871 if opts.pop('large', None):
872 toupload = getoutgoinglfiles(ui, repo, dest, **opts)
872 toupload = getoutgoinglfiles(ui, repo, dest, **opts)
873 if toupload is None:
873 if toupload is None:
874 ui.status(_('largefiles: No remote repo\n'))
874 ui.status(_('largefiles: No remote repo\n'))
875 else:
875 else:
876 ui.status(_('largefiles to upload:\n'))
876 ui.status(_('largefiles to upload:\n'))
877 for file in toupload:
877 for file in toupload:
878 ui.status(lfutil.splitstandin(file) + '\n')
878 ui.status(lfutil.splitstandin(file) + '\n')
879 ui.status('\n')
879 ui.status('\n')
880
880
881 def overridesummary(orig, ui, repo, *pats, **opts):
881 def overridesummary(orig, ui, repo, *pats, **opts):
882 try:
882 try:
883 repo.lfstatus = True
883 repo.lfstatus = True
884 orig(ui, repo, *pats, **opts)
884 orig(ui, repo, *pats, **opts)
885 finally:
885 finally:
886 repo.lfstatus = False
886 repo.lfstatus = False
887
887
888 if opts.pop('large', None):
888 if opts.pop('large', None):
889 toupload = getoutgoinglfiles(ui, repo, None, **opts)
889 toupload = getoutgoinglfiles(ui, repo, None, **opts)
890 if toupload is None:
890 if toupload is None:
891 ui.status(_('largefiles: No remote repo\n'))
891 ui.status(_('largefiles: No remote repo\n'))
892 else:
892 else:
893 ui.status(_('largefiles: %d to upload\n') % len(toupload))
893 ui.status(_('largefiles: %d to upload\n') % len(toupload))
894
894
895 def overrideaddremove(orig, ui, repo, *pats, **opts):
895 def overrideaddremove(orig, ui, repo, *pats, **opts):
896 # Get the list of missing largefiles so we can remove them
896 # Get the list of missing largefiles so we can remove them
897 lfdirstate = lfutil.openlfdirstate(ui, repo)
897 lfdirstate = lfutil.openlfdirstate(ui, repo)
898 s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
898 s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
899 False, False)
899 False, False)
900 (unsure, modified, added, removed, missing, unknown, ignored, clean) = s
900 (unsure, modified, added, removed, missing, unknown, ignored, clean) = s
901
901
902 # Call into the normal remove code, but the removing of the standin, we want
902 # Call into the normal remove code, but the removing of the standin, we want
903 # to have handled by original addremove. Monkey patching here makes sure
903 # to have handled by original addremove. Monkey patching here makes sure
904 # we don't remove the standin in the largefiles code, preventing a very
904 # we don't remove the standin in the largefiles code, preventing a very
905 # confused state later.
905 # confused state later.
906 if missing:
906 if missing:
907 repo._isaddremove = True
907 repo._isaddremove = True
908 removelargefiles(ui, repo, *missing, **opts)
908 removelargefiles(ui, repo, *missing, **opts)
909 repo._isaddremove = False
909 repo._isaddremove = False
910 # Call into the normal add code, and any files that *should* be added as
910 # Call into the normal add code, and any files that *should* be added as
911 # largefiles will be
911 # largefiles will be
912 addlargefiles(ui, repo, *pats, **opts)
912 addlargefiles(ui, repo, *pats, **opts)
913 # Now that we've handled largefiles, hand off to the original addremove
913 # Now that we've handled largefiles, hand off to the original addremove
914 # function to take care of the rest. Make sure it doesn't do anything with
914 # function to take care of the rest. Make sure it doesn't do anything with
915 # largefiles by installing a matcher that will ignore them.
915 # largefiles by installing a matcher that will ignore them.
916 installnormalfilesmatchfn(repo[None].manifest())
916 installnormalfilesmatchfn(repo[None].manifest())
917 result = orig(ui, repo, *pats, **opts)
917 result = orig(ui, repo, *pats, **opts)
918 restorematchfn()
918 restorematchfn()
919 return result
919 return result
920
920
921 # Calling purge with --all will cause the largefiles to be deleted.
921 # Calling purge with --all will cause the largefiles to be deleted.
922 # Override repo.status to prevent this from happening.
922 # Override repo.status to prevent this from happening.
923 def overridepurge(orig, ui, repo, *dirs, **opts):
923 def overridepurge(orig, ui, repo, *dirs, **opts):
924 oldstatus = repo.status
924 oldstatus = repo.status
925 def overridestatus(node1='.', node2=None, match=None, ignored=False,
925 def overridestatus(node1='.', node2=None, match=None, ignored=False,
926 clean=False, unknown=False, listsubrepos=False):
926 clean=False, unknown=False, listsubrepos=False):
927 r = oldstatus(node1, node2, match, ignored, clean, unknown,
927 r = oldstatus(node1, node2, match, ignored, clean, unknown,
928 listsubrepos)
928 listsubrepos)
929 lfdirstate = lfutil.openlfdirstate(ui, repo)
929 lfdirstate = lfutil.openlfdirstate(ui, repo)
930 modified, added, removed, deleted, unknown, ignored, clean = r
930 modified, added, removed, deleted, unknown, ignored, clean = r
931 unknown = [f for f in unknown if lfdirstate[f] == '?']
931 unknown = [f for f in unknown if lfdirstate[f] == '?']
932 ignored = [f for f in ignored if lfdirstate[f] == '?']
932 ignored = [f for f in ignored if lfdirstate[f] == '?']
933 return modified, added, removed, deleted, unknown, ignored, clean
933 return modified, added, removed, deleted, unknown, ignored, clean
934 repo.status = overridestatus
934 repo.status = overridestatus
935 orig(ui, repo, *dirs, **opts)
935 orig(ui, repo, *dirs, **opts)
936 repo.status = oldstatus
936 repo.status = oldstatus
937
937
938 def overriderollback(orig, ui, repo, **opts):
938 def overriderollback(orig, ui, repo, **opts):
939 result = orig(ui, repo, **opts)
939 result = orig(ui, repo, **opts)
940 merge.update(repo, node=None, branchmerge=False, force=True,
940 merge.update(repo, node=None, branchmerge=False, force=True,
941 partial=lfutil.isstandin)
941 partial=lfutil.isstandin)
942 wlock = repo.wlock()
942 wlock = repo.wlock()
943 try:
943 try:
944 lfdirstate = lfutil.openlfdirstate(ui, repo)
944 lfdirstate = lfutil.openlfdirstate(ui, repo)
945 lfiles = lfutil.listlfiles(repo)
945 lfiles = lfutil.listlfiles(repo)
946 oldlfiles = lfutil.listlfiles(repo, repo[None].parents()[0].rev())
946 oldlfiles = lfutil.listlfiles(repo, repo[None].parents()[0].rev())
947 for file in lfiles:
947 for file in lfiles:
948 if file in oldlfiles:
948 if file in oldlfiles:
949 lfdirstate.normallookup(file)
949 lfdirstate.normallookup(file)
950 else:
950 else:
951 lfdirstate.add(file)
951 lfdirstate.add(file)
952 lfdirstate.write()
952 lfdirstate.write()
953 finally:
953 finally:
954 wlock.release()
954 wlock.release()
955 return result
955 return result
956
956
957 def overridetransplant(orig, ui, repo, *revs, **opts):
957 def overridetransplant(orig, ui, repo, *revs, **opts):
958 try:
958 try:
959 oldstandins = lfutil.getstandinsstate(repo)
959 oldstandins = lfutil.getstandinsstate(repo)
960 repo._istransplanting = True
960 repo._istransplanting = True
961 result = orig(ui, repo, *revs, **opts)
961 result = orig(ui, repo, *revs, **opts)
962 newstandins = lfutil.getstandinsstate(repo)
962 newstandins = lfutil.getstandinsstate(repo)
963 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
963 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
964 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist,
964 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist,
965 printmessage=True)
965 printmessage=True)
966 finally:
966 finally:
967 repo._istransplanting = False
967 repo._istransplanting = False
968 return result
968 return result
@@ -1,458 +1,459 b''
1 # Copyright 2009-2010 Gregory P. Ward
1 # Copyright 2009-2010 Gregory P. Ward
2 # Copyright 2009-2010 Intelerad Medical Systems Incorporated
2 # Copyright 2009-2010 Intelerad Medical Systems Incorporated
3 # Copyright 2010-2011 Fog Creek Software
3 # Copyright 2010-2011 Fog Creek Software
4 # Copyright 2010-2011 Unity Technologies
4 # Copyright 2010-2011 Unity Technologies
5 #
5 #
6 # This software may be used and distributed according to the terms of the
6 # This software may be used and distributed according to the terms of the
7 # GNU General Public License version 2 or any later version.
7 # GNU General Public License version 2 or any later version.
8
8
9 '''setup for largefiles repositories: reposetup'''
9 '''setup for largefiles repositories: reposetup'''
10 import copy
10 import copy
11 import types
11 import types
12 import os
12 import os
13
13
14 from mercurial import context, error, manifest, match as match_, util
14 from mercurial import context, error, manifest, match as match_, util
15 from mercurial import node as node_
15 from mercurial import node as node_
16 from mercurial.i18n import _
16 from mercurial.i18n import _
17
17
18 import lfcommands
18 import lfcommands
19 import proto
19 import proto
20 import lfutil
20 import lfutil
21
21
22 def reposetup(ui, repo):
22 def reposetup(ui, repo):
23 # wire repositories should be given new wireproto functions but not the
23 # wire repositories should be given new wireproto functions but not the
24 # other largefiles modifications
24 # other largefiles modifications
25 if not repo.local():
25 if not repo.local():
26 return proto.wirereposetup(ui, repo)
26 return proto.wirereposetup(ui, repo)
27
27
28 for name in ('status', 'commitctx', 'commit', 'push'):
28 for name in ('status', 'commitctx', 'commit', 'push'):
29 method = getattr(repo, name)
29 method = getattr(repo, name)
30 if (isinstance(method, types.FunctionType) and
30 if (isinstance(method, types.FunctionType) and
31 method.func_name == 'wrap'):
31 method.func_name == 'wrap'):
32 ui.warn(_('largefiles: repo method %r appears to have already been'
32 ui.warn(_('largefiles: repo method %r appears to have already been'
33 ' wrapped by another extension: '
33 ' wrapped by another extension: '
34 'largefiles may behave incorrectly\n')
34 'largefiles may behave incorrectly\n')
35 % name)
35 % name)
36
36
37 class lfilesrepo(repo.__class__):
37 class lfilesrepo(repo.__class__):
38 lfstatus = False
38 lfstatus = False
39 def status_nolfiles(self, *args, **kwargs):
39 def status_nolfiles(self, *args, **kwargs):
40 return super(lfilesrepo, self).status(*args, **kwargs)
40 return super(lfilesrepo, self).status(*args, **kwargs)
41
41
42 # When lfstatus is set, return a context that gives the names
42 # When lfstatus is set, return a context that gives the names
43 # of largefiles instead of their corresponding standins and
43 # of largefiles instead of their corresponding standins and
44 # identifies the largefiles as always binary, regardless of
44 # identifies the largefiles as always binary, regardless of
45 # their actual contents.
45 # their actual contents.
46 def __getitem__(self, changeid):
46 def __getitem__(self, changeid):
47 ctx = super(lfilesrepo, self).__getitem__(changeid)
47 ctx = super(lfilesrepo, self).__getitem__(changeid)
48 if self.lfstatus:
48 if self.lfstatus:
49 class lfilesmanifestdict(manifest.manifestdict):
49 class lfilesmanifestdict(manifest.manifestdict):
50 def __contains__(self, filename):
50 def __contains__(self, filename):
51 if super(lfilesmanifestdict,
51 if super(lfilesmanifestdict,
52 self).__contains__(filename):
52 self).__contains__(filename):
53 return True
53 return True
54 return super(lfilesmanifestdict,
54 return super(lfilesmanifestdict,
55 self).__contains__(lfutil.standin(filename))
55 self).__contains__(lfutil.standin(filename))
56 class lfilesctx(ctx.__class__):
56 class lfilesctx(ctx.__class__):
57 def files(self):
57 def files(self):
58 filenames = super(lfilesctx, self).files()
58 filenames = super(lfilesctx, self).files()
59 return [lfutil.splitstandin(f) or f for f in filenames]
59 return [lfutil.splitstandin(f) or f for f in filenames]
60 def manifest(self):
60 def manifest(self):
61 man1 = super(lfilesctx, self).manifest()
61 man1 = super(lfilesctx, self).manifest()
62 man1.__class__ = lfilesmanifestdict
62 man1.__class__ = lfilesmanifestdict
63 return man1
63 return man1
64 def filectx(self, path, fileid=None, filelog=None):
64 def filectx(self, path, fileid=None, filelog=None):
65 try:
65 try:
66 if filelog is not None:
66 if filelog is not None:
67 result = super(lfilesctx, self).filectx(
67 result = super(lfilesctx, self).filectx(
68 path, fileid, filelog)
68 path, fileid, filelog)
69 else:
69 else:
70 result = super(lfilesctx, self).filectx(
70 result = super(lfilesctx, self).filectx(
71 path, fileid)
71 path, fileid)
72 except error.LookupError:
72 except error.LookupError:
73 # Adding a null character will cause Mercurial to
73 # Adding a null character will cause Mercurial to
74 # identify this as a binary file.
74 # identify this as a binary file.
75 if filelog is not None:
75 if filelog is not None:
76 result = super(lfilesctx, self).filectx(
76 result = super(lfilesctx, self).filectx(
77 lfutil.standin(path), fileid, filelog)
77 lfutil.standin(path), fileid, filelog)
78 else:
78 else:
79 result = super(lfilesctx, self).filectx(
79 result = super(lfilesctx, self).filectx(
80 lfutil.standin(path), fileid)
80 lfutil.standin(path), fileid)
81 olddata = result.data
81 olddata = result.data
82 result.data = lambda: olddata() + '\0'
82 result.data = lambda: olddata() + '\0'
83 return result
83 return result
84 ctx.__class__ = lfilesctx
84 ctx.__class__ = lfilesctx
85 return ctx
85 return ctx
86
86
87 # Figure out the status of big files and insert them into the
87 # Figure out the status of big files and insert them into the
88 # appropriate list in the result. Also removes standin files
88 # appropriate list in the result. Also removes standin files
89 # from the listing. Revert to the original status if
89 # from the listing. Revert to the original status if
90 # self.lfstatus is False.
90 # self.lfstatus is False.
91 def status(self, node1='.', node2=None, match=None, ignored=False,
91 def status(self, node1='.', node2=None, match=None, ignored=False,
92 clean=False, unknown=False, listsubrepos=False):
92 clean=False, unknown=False, listsubrepos=False):
93 listignored, listclean, listunknown = ignored, clean, unknown
93 listignored, listclean, listunknown = ignored, clean, unknown
94 if not self.lfstatus:
94 if not self.lfstatus:
95 return super(lfilesrepo, self).status(node1, node2, match,
95 return super(lfilesrepo, self).status(node1, node2, match,
96 listignored, listclean, listunknown, listsubrepos)
96 listignored, listclean, listunknown, listsubrepos)
97 else:
97 else:
98 # some calls in this function rely on the old version of status
98 # some calls in this function rely on the old version of status
99 self.lfstatus = False
99 self.lfstatus = False
100 if isinstance(node1, context.changectx):
100 if isinstance(node1, context.changectx):
101 ctx1 = node1
101 ctx1 = node1
102 else:
102 else:
103 ctx1 = repo[node1]
103 ctx1 = repo[node1]
104 if isinstance(node2, context.changectx):
104 if isinstance(node2, context.changectx):
105 ctx2 = node2
105 ctx2 = node2
106 else:
106 else:
107 ctx2 = repo[node2]
107 ctx2 = repo[node2]
108 working = ctx2.rev() is None
108 working = ctx2.rev() is None
109 parentworking = working and ctx1 == self['.']
109 parentworking = working and ctx1 == self['.']
110
110
111 def inctx(file, ctx):
111 def inctx(file, ctx):
112 try:
112 try:
113 if ctx.rev() is None:
113 if ctx.rev() is None:
114 return file in ctx.manifest()
114 return file in ctx.manifest()
115 ctx[file]
115 ctx[file]
116 return True
116 return True
117 except KeyError:
117 except KeyError:
118 return False
118 return False
119
119
120 if match is None:
120 if match is None:
121 match = match_.always(self.root, self.getcwd())
121 match = match_.always(self.root, self.getcwd())
122
122
123 # First check if there were files specified on the
123 # First check if there were files specified on the
124 # command line. If there were, and none of them were
124 # command line. If there were, and none of them were
125 # largefiles, we should just bail here and let super
125 # largefiles, we should just bail here and let super
126 # handle it -- thus gaining a big performance boost.
126 # handle it -- thus gaining a big performance boost.
127 lfdirstate = lfutil.openlfdirstate(ui, self)
127 lfdirstate = lfutil.openlfdirstate(ui, self)
128 if match.files() and not match.anypats():
128 if match.files() and not match.anypats():
129 for f in lfdirstate:
129 for f in lfdirstate:
130 if match(f):
130 if match(f):
131 break
131 break
132 else:
132 else:
133 return super(lfilesrepo, self).status(node1, node2,
133 return super(lfilesrepo, self).status(node1, node2,
134 match, listignored, listclean,
134 match, listignored, listclean,
135 listunknown, listsubrepos)
135 listunknown, listsubrepos)
136
136
137 # Create a copy of match that matches standins instead
137 # Create a copy of match that matches standins instead
138 # of largefiles.
138 # of largefiles.
139 def tostandin(file):
139 def tostandin(file):
140 if inctx(lfutil.standin(file), ctx2):
140 if inctx(lfutil.standin(file), ctx2):
141 return lfutil.standin(file)
141 return lfutil.standin(file)
142 return file
142 return file
143
143
144 # Create a function that we can use to override what is
144 # Create a function that we can use to override what is
145 # normally the ignore matcher. We've already checked
145 # normally the ignore matcher. We've already checked
146 # for ignored files on the first dirstate walk, and
146 # for ignored files on the first dirstate walk, and
147 # unecessarily re-checking here causes a huge performance
147 # unecessarily re-checking here causes a huge performance
148 # hit because lfdirstate only knows about largefiles
148 # hit because lfdirstate only knows about largefiles
149 def _ignoreoverride(self):
149 def _ignoreoverride(self):
150 return False
150 return False
151
151
152 m = copy.copy(match)
152 m = copy.copy(match)
153 m._files = [tostandin(f) for f in m._files]
153 m._files = [tostandin(f) for f in m._files]
154
154
155 # Get ignored files here even if we weren't asked for them; we
155 # Get ignored files here even if we weren't asked for them; we
156 # must use the result here for filtering later
156 # must use the result here for filtering later
157 result = super(lfilesrepo, self).status(node1, node2, m,
157 result = super(lfilesrepo, self).status(node1, node2, m,
158 True, clean, unknown, listsubrepos)
158 True, clean, unknown, listsubrepos)
159 if working:
159 if working:
160 try:
160 try:
161 # Any non-largefiles that were explicitly listed must be
161 # Any non-largefiles that were explicitly listed must be
162 # taken out or lfdirstate.status will report an error.
162 # taken out or lfdirstate.status will report an error.
163 # The status of these files was already computed using
163 # The status of these files was already computed using
164 # super's status.
164 # super's status.
165 # Override lfdirstate's ignore matcher to not do
165 # Override lfdirstate's ignore matcher to not do
166 # anything
166 # anything
167 origignore = lfdirstate._ignore
167 origignore = lfdirstate._ignore
168 lfdirstate._ignore = _ignoreoverride
168 lfdirstate._ignore = _ignoreoverride
169
169
170 match._files = [f for f in match._files if f in
170 match._files = [f for f in match._files if f in
171 lfdirstate]
171 lfdirstate]
172 # Don't waste time getting the ignored and unknown
172 # Don't waste time getting the ignored and unknown
173 # files again; we already have them
173 # files again; we already have them
174 s = lfdirstate.status(match, [], False,
174 s = lfdirstate.status(match, [], False,
175 listclean, False)
175 listclean, False)
176 (unsure, modified, added, removed, missing, unknown,
176 (unsure, modified, added, removed, missing, unknown,
177 ignored, clean) = s
177 ignored, clean) = s
178 # Replace the list of ignored and unknown files with
178 # Replace the list of ignored and unknown files with
179 # the previously caclulated lists, and strip out the
179 # the previously caclulated lists, and strip out the
180 # largefiles
180 # largefiles
181 lfiles = set(lfdirstate._map)
181 lfiles = set(lfdirstate._map)
182 ignored = set(result[5]).difference(lfiles)
182 ignored = set(result[5]).difference(lfiles)
183 unknown = set(result[4]).difference(lfiles)
183 unknown = set(result[4]).difference(lfiles)
184 if parentworking:
184 if parentworking:
185 for lfile in unsure:
185 for lfile in unsure:
186 standin = lfutil.standin(lfile)
186 standin = lfutil.standin(lfile)
187 if standin not in ctx1:
187 if standin not in ctx1:
188 # from second parent
188 # from second parent
189 modified.append(lfile)
189 modified.append(lfile)
190 elif ctx1[standin].data().strip() \
190 elif ctx1[standin].data().strip() \
191 != lfutil.hashfile(self.wjoin(lfile)):
191 != lfutil.hashfile(self.wjoin(lfile)):
192 modified.append(lfile)
192 modified.append(lfile)
193 else:
193 else:
194 clean.append(lfile)
194 clean.append(lfile)
195 lfdirstate.normal(lfile)
195 lfdirstate.normal(lfile)
196 else:
196 else:
197 tocheck = unsure + modified + added + clean
197 tocheck = unsure + modified + added + clean
198 modified, added, clean = [], [], []
198 modified, added, clean = [], [], []
199
199
200 for lfile in tocheck:
200 for lfile in tocheck:
201 standin = lfutil.standin(lfile)
201 standin = lfutil.standin(lfile)
202 if inctx(standin, ctx1):
202 if inctx(standin, ctx1):
203 if ctx1[standin].data().strip() != \
203 if ctx1[standin].data().strip() != \
204 lfutil.hashfile(self.wjoin(lfile)):
204 lfutil.hashfile(self.wjoin(lfile)):
205 modified.append(lfile)
205 modified.append(lfile)
206 else:
206 else:
207 clean.append(lfile)
207 clean.append(lfile)
208 else:
208 else:
209 added.append(lfile)
209 added.append(lfile)
210 finally:
210 finally:
211 # Replace the original ignore function
211 # Replace the original ignore function
212 lfdirstate._ignore = origignore
212 lfdirstate._ignore = origignore
213
213
214 for standin in ctx1.manifest():
214 for standin in ctx1.manifest():
215 if not lfutil.isstandin(standin):
215 if not lfutil.isstandin(standin):
216 continue
216 continue
217 lfile = lfutil.splitstandin(standin)
217 lfile = lfutil.splitstandin(standin)
218 if not match(lfile):
218 if not match(lfile):
219 continue
219 continue
220 if lfile not in lfdirstate:
220 if lfile not in lfdirstate:
221 removed.append(lfile)
221 removed.append(lfile)
222
222
223 # Filter result lists
223 # Filter result lists
224 result = list(result)
224 result = list(result)
225
225
226 # Largefiles are not really removed when they're
226 # Largefiles are not really removed when they're
227 # still in the normal dirstate. Likewise, normal
227 # still in the normal dirstate. Likewise, normal
228 # files are not really removed if it's still in
228 # files are not really removed if it's still in
229 # lfdirstate. This happens in merges where files
229 # lfdirstate. This happens in merges where files
230 # change type.
230 # change type.
231 removed = [f for f in removed if f not in repo.dirstate]
231 removed = [f for f in removed if f not in repo.dirstate]
232 result[2] = [f for f in result[2] if f not in lfdirstate]
232 result[2] = [f for f in result[2] if f not in lfdirstate]
233
233
234 # Unknown files
234 # Unknown files
235 unknown = set(unknown).difference(ignored)
235 unknown = set(unknown).difference(ignored)
236 result[4] = [f for f in unknown
236 result[4] = [f for f in unknown
237 if (repo.dirstate[f] == '?' and
237 if (repo.dirstate[f] == '?' and
238 not lfutil.isstandin(f))]
238 not lfutil.isstandin(f))]
239 # Ignored files were calculated earlier by the dirstate,
239 # Ignored files were calculated earlier by the dirstate,
240 # and we already stripped out the largefiles from the list
240 # and we already stripped out the largefiles from the list
241 result[5] = ignored
241 result[5] = ignored
242 # combine normal files and largefiles
242 # combine normal files and largefiles
243 normals = [[fn for fn in filelist
243 normals = [[fn for fn in filelist
244 if not lfutil.isstandin(fn)]
244 if not lfutil.isstandin(fn)]
245 for filelist in result]
245 for filelist in result]
246 lfiles = (modified, added, removed, missing, [], [], clean)
246 lfiles = (modified, added, removed, missing, [], [], clean)
247 result = [sorted(list1 + list2)
247 result = [sorted(list1 + list2)
248 for (list1, list2) in zip(normals, lfiles)]
248 for (list1, list2) in zip(normals, lfiles)]
249 else:
249 else:
250 def toname(f):
250 def toname(f):
251 if lfutil.isstandin(f):
251 if lfutil.isstandin(f):
252 return lfutil.splitstandin(f)
252 return lfutil.splitstandin(f)
253 return f
253 return f
254 result = [[toname(f) for f in items] for items in result]
254 result = [[toname(f) for f in items] for items in result]
255
255
256 if not listunknown:
256 if not listunknown:
257 result[4] = []
257 result[4] = []
258 if not listignored:
258 if not listignored:
259 result[5] = []
259 result[5] = []
260 if not listclean:
260 if not listclean:
261 result[6] = []
261 result[6] = []
262 self.lfstatus = True
262 self.lfstatus = True
263 return result
263 return result
264
264
265 # As part of committing, copy all of the largefiles into the
265 # As part of committing, copy all of the largefiles into the
266 # cache.
266 # cache.
267 def commitctx(self, *args, **kwargs):
267 def commitctx(self, *args, **kwargs):
268 node = super(lfilesrepo, self).commitctx(*args, **kwargs)
268 node = super(lfilesrepo, self).commitctx(*args, **kwargs)
269 lfutil.copyalltostore(self, node)
269 lfutil.copyalltostore(self, node)
270 return node
270 return node
271
271
272 # Before commit, largefile standins have not had their
272 # Before commit, largefile standins have not had their
273 # contents updated to reflect the hash of their largefile.
273 # contents updated to reflect the hash of their largefile.
274 # Do that here.
274 # Do that here.
275 def commit(self, text="", user=None, date=None, match=None,
275 def commit(self, text="", user=None, date=None, match=None,
276 force=False, editor=False, extra={}):
276 force=False, editor=False, extra={}):
277 orig = super(lfilesrepo, self).commit
277 orig = super(lfilesrepo, self).commit
278
278
279 wlock = repo.wlock()
279 wlock = repo.wlock()
280 try:
280 try:
281 # Case 0: Rebase or Transplant
281 # Case 0: Rebase or Transplant
282 # We have to take the time to pull down the new largefiles now.
282 # We have to take the time to pull down the new largefiles now.
283 # Otherwise, any largefiles that were modified in the
283 # Otherwise, any largefiles that were modified in the
284 # destination changesets get overwritten, either by the rebase
284 # destination changesets get overwritten, either by the rebase
285 # or in the first commit after the rebase or transplant.
285 # or in the first commit after the rebase or transplant.
286 # updatelfiles will update the dirstate to mark any pulled
286 # updatelfiles will update the dirstate to mark any pulled
287 # largefiles as modified
287 # largefiles as modified
288 if getattr(repo, "_isrebasing", False) or \
288 if getattr(repo, "_isrebasing", False) or \
289 getattr(repo, "_istransplanting", False):
289 getattr(repo, "_istransplanting", False):
290 lfcommands.updatelfiles(repo.ui, repo, filelist=None,
290 lfcommands.updatelfiles(repo.ui, repo, filelist=None,
291 printmessage=False)
291 printmessage=False)
292 result = orig(text=text, user=user, date=date, match=match,
292 result = orig(text=text, user=user, date=date, match=match,
293 force=force, editor=editor, extra=extra)
293 force=force, editor=editor, extra=extra)
294 return result
294 return result
295 # Case 1: user calls commit with no specific files or
295 # Case 1: user calls commit with no specific files or
296 # include/exclude patterns: refresh and commit all files that
296 # include/exclude patterns: refresh and commit all files that
297 # are "dirty".
297 # are "dirty".
298 if ((match is None) or
298 if ((match is None) or
299 (not match.anypats() and not match.files())):
299 (not match.anypats() and not match.files())):
300 # Spend a bit of time here to get a list of files we know
300 # Spend a bit of time here to get a list of files we know
301 # are modified so we can compare only against those.
301 # are modified so we can compare only against those.
302 # It can cost a lot of time (several seconds)
302 # It can cost a lot of time (several seconds)
303 # otherwise to update all standins if the largefiles are
303 # otherwise to update all standins if the largefiles are
304 # large.
304 # large.
305 lfdirstate = lfutil.openlfdirstate(ui, self)
305 lfdirstate = lfutil.openlfdirstate(ui, self)
306 dirtymatch = match_.always(repo.root, repo.getcwd())
306 dirtymatch = match_.always(repo.root, repo.getcwd())
307 s = lfdirstate.status(dirtymatch, [], False, False, False)
307 s = lfdirstate.status(dirtymatch, [], False, False, False)
308 modifiedfiles = []
308 modifiedfiles = []
309 for i in s:
309 for i in s:
310 modifiedfiles.extend(i)
310 modifiedfiles.extend(i)
311 lfiles = lfutil.listlfiles(self)
311 lfiles = lfutil.listlfiles(self)
312 # this only loops through largefiles that exist (not
312 # this only loops through largefiles that exist (not
313 # removed/renamed)
313 # removed/renamed)
314 for lfile in lfiles:
314 for lfile in lfiles:
315 if lfile in modifiedfiles:
315 if lfile in modifiedfiles:
316 if os.path.exists(self.wjoin(lfutil.standin(lfile))):
316 if os.path.exists(
317 self.wjoin(lfutil.standin(lfile))):
317 # this handles the case where a rebase is being
318 # this handles the case where a rebase is being
318 # performed and the working copy is not updated
319 # performed and the working copy is not updated
319 # yet.
320 # yet.
320 if os.path.exists(self.wjoin(lfile)):
321 if os.path.exists(self.wjoin(lfile)):
321 lfutil.updatestandin(self,
322 lfutil.updatestandin(self,
322 lfutil.standin(lfile))
323 lfutil.standin(lfile))
323 lfdirstate.normal(lfile)
324 lfdirstate.normal(lfile)
324 for lfile in lfdirstate:
325 for lfile in lfdirstate:
325 if lfile in modifiedfiles:
326 if lfile in modifiedfiles:
326 if not os.path.exists(
327 if not os.path.exists(
327 repo.wjoin(lfutil.standin(lfile))):
328 repo.wjoin(lfutil.standin(lfile))):
328 lfdirstate.drop(lfile)
329 lfdirstate.drop(lfile)
329
330
330 result = orig(text=text, user=user, date=date, match=match,
331 result = orig(text=text, user=user, date=date, match=match,
331 force=force, editor=editor, extra=extra)
332 force=force, editor=editor, extra=extra)
332 # This needs to be after commit; otherwise precommit hooks
333 # This needs to be after commit; otherwise precommit hooks
333 # get the wrong status
334 # get the wrong status
334 lfdirstate.write()
335 lfdirstate.write()
335 return result
336 return result
336
337
337 for f in match.files():
338 for f in match.files():
338 if lfutil.isstandin(f):
339 if lfutil.isstandin(f):
339 raise util.Abort(
340 raise util.Abort(
340 _('file "%s" is a largefile standin') % f,
341 _('file "%s" is a largefile standin') % f,
341 hint=('commit the largefile itself instead'))
342 hint=('commit the largefile itself instead'))
342
343
343 # Case 2: user calls commit with specified patterns: refresh
344 # Case 2: user calls commit with specified patterns: refresh
344 # any matching big files.
345 # any matching big files.
345 smatcher = lfutil.composestandinmatcher(self, match)
346 smatcher = lfutil.composestandinmatcher(self, match)
346 standins = lfutil.dirstatewalk(self.dirstate, smatcher)
347 standins = lfutil.dirstatewalk(self.dirstate, smatcher)
347
348
348 # No matching big files: get out of the way and pass control to
349 # No matching big files: get out of the way and pass control to
349 # the usual commit() method.
350 # the usual commit() method.
350 if not standins:
351 if not standins:
351 return orig(text=text, user=user, date=date, match=match,
352 return orig(text=text, user=user, date=date, match=match,
352 force=force, editor=editor, extra=extra)
353 force=force, editor=editor, extra=extra)
353
354
354 # Refresh all matching big files. It's possible that the
355 # Refresh all matching big files. It's possible that the
355 # commit will end up failing, in which case the big files will
356 # commit will end up failing, in which case the big files will
356 # stay refreshed. No harm done: the user modified them and
357 # stay refreshed. No harm done: the user modified them and
357 # asked to commit them, so sooner or later we're going to
358 # asked to commit them, so sooner or later we're going to
358 # refresh the standins. Might as well leave them refreshed.
359 # refresh the standins. Might as well leave them refreshed.
359 lfdirstate = lfutil.openlfdirstate(ui, self)
360 lfdirstate = lfutil.openlfdirstate(ui, self)
360 for standin in standins:
361 for standin in standins:
361 lfile = lfutil.splitstandin(standin)
362 lfile = lfutil.splitstandin(standin)
362 if lfdirstate[lfile] <> 'r':
363 if lfdirstate[lfile] <> 'r':
363 lfutil.updatestandin(self, standin)
364 lfutil.updatestandin(self, standin)
364 lfdirstate.normal(lfile)
365 lfdirstate.normal(lfile)
365 else:
366 else:
366 lfdirstate.drop(lfile)
367 lfdirstate.drop(lfile)
367
368
368 # Cook up a new matcher that only matches regular files or
369 # Cook up a new matcher that only matches regular files or
369 # standins corresponding to the big files requested by the
370 # standins corresponding to the big files requested by the
370 # user. Have to modify _files to prevent commit() from
371 # user. Have to modify _files to prevent commit() from
371 # complaining "not tracked" for big files.
372 # complaining "not tracked" for big files.
372 lfiles = lfutil.listlfiles(repo)
373 lfiles = lfutil.listlfiles(repo)
373 match = copy.copy(match)
374 match = copy.copy(match)
374 origmatchfn = match.matchfn
375 origmatchfn = match.matchfn
375
376
376 # Check both the list of largefiles and the list of
377 # Check both the list of largefiles and the list of
377 # standins because if a largefile was removed, it
378 # standins because if a largefile was removed, it
378 # won't be in the list of largefiles at this point
379 # won't be in the list of largefiles at this point
379 match._files += sorted(standins)
380 match._files += sorted(standins)
380
381
381 actualfiles = []
382 actualfiles = []
382 for f in match._files:
383 for f in match._files:
383 fstandin = lfutil.standin(f)
384 fstandin = lfutil.standin(f)
384
385
385 # ignore known largefiles and standins
386 # ignore known largefiles and standins
386 if f in lfiles or fstandin in standins:
387 if f in lfiles or fstandin in standins:
387 continue
388 continue
388
389
389 # append directory separator to avoid collisions
390 # append directory separator to avoid collisions
390 if not fstandin.endswith(os.sep):
391 if not fstandin.endswith(os.sep):
391 fstandin += os.sep
392 fstandin += os.sep
392
393
393 # prevalidate matching standin directories
394 # prevalidate matching standin directories
394 if util.any(st for st in match._files
395 if util.any(st for st in match._files
395 if st.startswith(fstandin)):
396 if st.startswith(fstandin)):
396 continue
397 continue
397 actualfiles.append(f)
398 actualfiles.append(f)
398 match._files = actualfiles
399 match._files = actualfiles
399
400
400 def matchfn(f):
401 def matchfn(f):
401 if origmatchfn(f):
402 if origmatchfn(f):
402 return f not in lfiles
403 return f not in lfiles
403 else:
404 else:
404 return f in standins
405 return f in standins
405
406
406 match.matchfn = matchfn
407 match.matchfn = matchfn
407 result = orig(text=text, user=user, date=date, match=match,
408 result = orig(text=text, user=user, date=date, match=match,
408 force=force, editor=editor, extra=extra)
409 force=force, editor=editor, extra=extra)
409 # This needs to be after commit; otherwise precommit hooks
410 # This needs to be after commit; otherwise precommit hooks
410 # get the wrong status
411 # get the wrong status
411 lfdirstate.write()
412 lfdirstate.write()
412 return result
413 return result
413 finally:
414 finally:
414 wlock.release()
415 wlock.release()
415
416
416 def push(self, remote, force=False, revs=None, newbranch=False):
417 def push(self, remote, force=False, revs=None, newbranch=False):
417 o = lfutil.findoutgoing(repo, remote, force)
418 o = lfutil.findoutgoing(repo, remote, force)
418 if o:
419 if o:
419 toupload = set()
420 toupload = set()
420 o = repo.changelog.nodesbetween(o, revs)[0]
421 o = repo.changelog.nodesbetween(o, revs)[0]
421 for n in o:
422 for n in o:
422 parents = [p for p in repo.changelog.parents(n)
423 parents = [p for p in repo.changelog.parents(n)
423 if p != node_.nullid]
424 if p != node_.nullid]
424 ctx = repo[n]
425 ctx = repo[n]
425 files = set(ctx.files())
426 files = set(ctx.files())
426 if len(parents) == 2:
427 if len(parents) == 2:
427 mc = ctx.manifest()
428 mc = ctx.manifest()
428 mp1 = ctx.parents()[0].manifest()
429 mp1 = ctx.parents()[0].manifest()
429 mp2 = ctx.parents()[1].manifest()
430 mp2 = ctx.parents()[1].manifest()
430 for f in mp1:
431 for f in mp1:
431 if f not in mc:
432 if f not in mc:
432 files.add(f)
433 files.add(f)
433 for f in mp2:
434 for f in mp2:
434 if f not in mc:
435 if f not in mc:
435 files.add(f)
436 files.add(f)
436 for f in mc:
437 for f in mc:
437 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f,
438 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f,
438 None):
439 None):
439 files.add(f)
440 files.add(f)
440
441
441 toupload = toupload.union(
442 toupload = toupload.union(
442 set([ctx[f].data().strip()
443 set([ctx[f].data().strip()
443 for f in files
444 for f in files
444 if lfutil.isstandin(f) and f in ctx]))
445 if lfutil.isstandin(f) and f in ctx]))
445 lfcommands.uploadlfiles(ui, self, remote, toupload)
446 lfcommands.uploadlfiles(ui, self, remote, toupload)
446 return super(lfilesrepo, self).push(remote, force, revs,
447 return super(lfilesrepo, self).push(remote, force, revs,
447 newbranch)
448 newbranch)
448
449
449 repo.__class__ = lfilesrepo
450 repo.__class__ = lfilesrepo
450
451
451 def checkrequireslfiles(ui, repo, **kwargs):
452 def checkrequireslfiles(ui, repo, **kwargs):
452 if 'largefiles' not in repo.requirements and util.any(
453 if 'largefiles' not in repo.requirements and util.any(
453 lfutil.shortname+'/' in f[0] for f in repo.store.datafiles()):
454 lfutil.shortname+'/' in f[0] for f in repo.store.datafiles()):
454 repo.requirements.add('largefiles')
455 repo.requirements.add('largefiles')
455 repo._writerequirements()
456 repo._writerequirements()
456
457
457 ui.setconfig('hooks', 'changegroup.lfiles', checkrequireslfiles)
458 ui.setconfig('hooks', 'changegroup.lfiles', checkrequireslfiles)
458 ui.setconfig('hooks', 'commit.lfiles', checkrequireslfiles)
459 ui.setconfig('hooks', 'commit.lfiles', checkrequireslfiles)
@@ -1,656 +1,650 b''
1 $ check_code="$TESTDIR"/../contrib/check-code.py
1 $ check_code="$TESTDIR"/../contrib/check-code.py
2 $ cd "$TESTDIR"/..
2 $ cd "$TESTDIR"/..
3 $ if ! hg identify -q > /dev/null; then
3 $ if ! hg identify -q > /dev/null; then
4 > echo "skipped: not a Mercurial working dir" >&2
4 > echo "skipped: not a Mercurial working dir" >&2
5 > exit 80
5 > exit 80
6 > fi
6 > fi
7 $ hg manifest | xargs "$check_code" || echo 'FAILURE IS NOT AN OPTION!!!'
7 $ hg manifest | xargs "$check_code" || echo 'FAILURE IS NOT AN OPTION!!!'
8
8
9 $ hg manifest | xargs "$check_code" --warnings --nolineno --per-file=0 || true
9 $ hg manifest | xargs "$check_code" --warnings --nolineno --per-file=0 || true
10 contrib/check-code.py:0:
10 contrib/check-code.py:0:
11 > # (r'^\s+[^_ \n][^_. \n]+_[^_\n]+\s*=', "don't use underbars in identifiers"),
11 > # (r'^\s+[^_ \n][^_. \n]+_[^_\n]+\s*=', "don't use underbars in identifiers"),
12 warning: line over 80 characters
12 warning: line over 80 characters
13 contrib/perf.py:0:
13 contrib/perf.py:0:
14 > except:
14 > except:
15 warning: naked except clause
15 warning: naked except clause
16 contrib/perf.py:0:
16 contrib/perf.py:0:
17 > #timer(lambda: sum(map(len, repo.dirstate.status(m, [], False, False, False))))
17 > #timer(lambda: sum(map(len, repo.dirstate.status(m, [], False, False, False))))
18 warning: line over 80 characters
18 warning: line over 80 characters
19 contrib/perf.py:0:
19 contrib/perf.py:0:
20 > except:
20 > except:
21 warning: naked except clause
21 warning: naked except clause
22 contrib/setup3k.py:0:
22 contrib/setup3k.py:0:
23 > except:
23 > except:
24 warning: naked except clause
24 warning: naked except clause
25 contrib/setup3k.py:0:
25 contrib/setup3k.py:0:
26 > except:
26 > except:
27 warning: naked except clause
27 warning: naked except clause
28 contrib/setup3k.py:0:
28 contrib/setup3k.py:0:
29 > except:
29 > except:
30 warning: naked except clause
30 warning: naked except clause
31 warning: naked except clause
31 warning: naked except clause
32 warning: naked except clause
32 warning: naked except clause
33 contrib/shrink-revlog.py:0:
33 contrib/shrink-revlog.py:0:
34 > '(You can delete those files when you are satisfied that your\n'
34 > '(You can delete those files when you are satisfied that your\n'
35 warning: line over 80 characters
35 warning: line over 80 characters
36 contrib/shrink-revlog.py:0:
36 contrib/shrink-revlog.py:0:
37 > ('', 'sort', 'reversepostorder', 'name of sort algorithm to use'),
37 > ('', 'sort', 'reversepostorder', 'name of sort algorithm to use'),
38 warning: line over 80 characters
38 warning: line over 80 characters
39 contrib/shrink-revlog.py:0:
39 contrib/shrink-revlog.py:0:
40 > [('', 'revlog', '', _('index (.i) file of the revlog to shrink')),
40 > [('', 'revlog', '', _('index (.i) file of the revlog to shrink')),
41 warning: line over 80 characters
41 warning: line over 80 characters
42 contrib/shrink-revlog.py:0:
42 contrib/shrink-revlog.py:0:
43 > except:
43 > except:
44 warning: naked except clause
44 warning: naked except clause
45 doc/gendoc.py:0:
45 doc/gendoc.py:0:
46 > "together with Mercurial. Help for other extensions is available "
46 > "together with Mercurial. Help for other extensions is available "
47 warning: line over 80 characters
47 warning: line over 80 characters
48 hgext/bugzilla.py:0:
48 hgext/bugzilla.py:0:
49 > raise util.Abort(_('cannot find bugzilla user id for %s or %s') %
49 > raise util.Abort(_('cannot find bugzilla user id for %s or %s') %
50 warning: line over 80 characters
50 warning: line over 80 characters
51 hgext/bugzilla.py:0:
51 hgext/bugzilla.py:0:
52 > bzdir = self.ui.config('bugzilla', 'bzdir', '/var/www/html/bugzilla')
52 > bzdir = self.ui.config('bugzilla', 'bzdir', '/var/www/html/bugzilla')
53 warning: line over 80 characters
53 warning: line over 80 characters
54 hgext/convert/__init__.py:0:
54 hgext/convert/__init__.py:0:
55 > ('', 'ancestors', '', _('show current changeset in ancestor branches')),
55 > ('', 'ancestors', '', _('show current changeset in ancestor branches')),
56 warning: line over 80 characters
56 warning: line over 80 characters
57 hgext/convert/bzr.py:0:
57 hgext/convert/bzr.py:0:
58 > except:
58 > except:
59 warning: naked except clause
59 warning: naked except clause
60 hgext/convert/common.py:0:
60 hgext/convert/common.py:0:
61 > except:
61 > except:
62 warning: naked except clause
62 warning: naked except clause
63 hgext/convert/common.py:0:
63 hgext/convert/common.py:0:
64 > except:
64 > except:
65 warning: naked except clause
65 warning: naked except clause
66 warning: naked except clause
66 warning: naked except clause
67 hgext/convert/convcmd.py:0:
67 hgext/convert/convcmd.py:0:
68 > except:
68 > except:
69 warning: naked except clause
69 warning: naked except clause
70 hgext/convert/cvs.py:0:
70 hgext/convert/cvs.py:0:
71 > # /1 :pserver:user@example.com:2401/cvsroot/foo Ah<Z
71 > # /1 :pserver:user@example.com:2401/cvsroot/foo Ah<Z
72 warning: line over 80 characters
72 warning: line over 80 characters
73 hgext/convert/cvsps.py:0:
73 hgext/convert/cvsps.py:0:
74 > assert len(branches) == 1, 'unknown branch: %s' % e.mergepoint
74 > assert len(branches) == 1, 'unknown branch: %s' % e.mergepoint
75 warning: line over 80 characters
75 warning: line over 80 characters
76 hgext/convert/cvsps.py:0:
76 hgext/convert/cvsps.py:0:
77 > ui.write('Ancestors: %s\n' % (','.join(r)))
77 > ui.write('Ancestors: %s\n' % (','.join(r)))
78 warning: unwrapped ui message
78 warning: unwrapped ui message
79 hgext/convert/cvsps.py:0:
79 hgext/convert/cvsps.py:0:
80 > ui.write('Parent: %d\n' % cs.parents[0].id)
80 > ui.write('Parent: %d\n' % cs.parents[0].id)
81 warning: unwrapped ui message
81 warning: unwrapped ui message
82 hgext/convert/cvsps.py:0:
82 hgext/convert/cvsps.py:0:
83 > ui.write('Parents: %s\n' %
83 > ui.write('Parents: %s\n' %
84 warning: unwrapped ui message
84 warning: unwrapped ui message
85 hgext/convert/cvsps.py:0:
85 hgext/convert/cvsps.py:0:
86 > except:
86 > except:
87 warning: naked except clause
87 warning: naked except clause
88 hgext/convert/cvsps.py:0:
88 hgext/convert/cvsps.py:0:
89 > ui.write('Branchpoints: %s \n' % ', '.join(branchpoints))
89 > ui.write('Branchpoints: %s \n' % ', '.join(branchpoints))
90 warning: unwrapped ui message
90 warning: unwrapped ui message
91 hgext/convert/cvsps.py:0:
91 hgext/convert/cvsps.py:0:
92 > ui.write('Author: %s\n' % cs.author)
92 > ui.write('Author: %s\n' % cs.author)
93 warning: unwrapped ui message
93 warning: unwrapped ui message
94 hgext/convert/cvsps.py:0:
94 hgext/convert/cvsps.py:0:
95 > ui.write('Branch: %s\n' % (cs.branch or 'HEAD'))
95 > ui.write('Branch: %s\n' % (cs.branch or 'HEAD'))
96 warning: unwrapped ui message
96 warning: unwrapped ui message
97 hgext/convert/cvsps.py:0:
97 hgext/convert/cvsps.py:0:
98 > ui.write('Date: %s\n' % util.datestr(cs.date,
98 > ui.write('Date: %s\n' % util.datestr(cs.date,
99 warning: unwrapped ui message
99 warning: unwrapped ui message
100 hgext/convert/cvsps.py:0:
100 hgext/convert/cvsps.py:0:
101 > ui.write('Log:\n')
101 > ui.write('Log:\n')
102 warning: unwrapped ui message
102 warning: unwrapped ui message
103 hgext/convert/cvsps.py:0:
103 hgext/convert/cvsps.py:0:
104 > ui.write('Members: \n')
104 > ui.write('Members: \n')
105 warning: unwrapped ui message
105 warning: unwrapped ui message
106 hgext/convert/cvsps.py:0:
106 hgext/convert/cvsps.py:0:
107 > ui.write('PatchSet %d \n' % cs.id)
107 > ui.write('PatchSet %d \n' % cs.id)
108 warning: unwrapped ui message
108 warning: unwrapped ui message
109 hgext/convert/cvsps.py:0:
109 hgext/convert/cvsps.py:0:
110 > ui.write('Tag%s: %s \n' % (['', 's'][len(cs.tags) > 1],
110 > ui.write('Tag%s: %s \n' % (['', 's'][len(cs.tags) > 1],
111 warning: unwrapped ui message
111 warning: unwrapped ui message
112 hgext/convert/git.py:0:
112 hgext/convert/git.py:0:
113 > except:
113 > except:
114 warning: naked except clause
114 warning: naked except clause
115 hgext/convert/git.py:0:
115 hgext/convert/git.py:0:
116 > fh = self.gitopen('git diff-tree --name-only --root -r %s "%s^%s" --'
116 > fh = self.gitopen('git diff-tree --name-only --root -r %s "%s^%s" --'
117 warning: line over 80 characters
117 warning: line over 80 characters
118 hgext/convert/hg.py:0:
118 hgext/convert/hg.py:0:
119 > # detect missing revlogs and abort on errors or populate self.ignored
119 > # detect missing revlogs and abort on errors or populate self.ignored
120 warning: line over 80 characters
120 warning: line over 80 characters
121 hgext/convert/hg.py:0:
121 hgext/convert/hg.py:0:
122 > except:
122 > except:
123 warning: naked except clause
123 warning: naked except clause
124 warning: naked except clause
124 warning: naked except clause
125 hgext/convert/hg.py:0:
125 hgext/convert/hg.py:0:
126 > except:
126 > except:
127 warning: naked except clause
127 warning: naked except clause
128 hgext/convert/monotone.py:0:
128 hgext/convert/monotone.py:0:
129 > except:
129 > except:
130 warning: naked except clause
130 warning: naked except clause
131 hgext/convert/monotone.py:0:
131 hgext/convert/monotone.py:0:
132 > except:
132 > except:
133 warning: naked except clause
133 warning: naked except clause
134 hgext/convert/subversion.py:0:
134 hgext/convert/subversion.py:0:
135 > raise util.Abort(_('svn: branch has no revision %s') % to_revnum)
135 > raise util.Abort(_('svn: branch has no revision %s') % to_revnum)
136 warning: line over 80 characters
136 warning: line over 80 characters
137 hgext/convert/subversion.py:0:
137 hgext/convert/subversion.py:0:
138 > except:
138 > except:
139 warning: naked except clause
139 warning: naked except clause
140 hgext/convert/subversion.py:0:
140 hgext/convert/subversion.py:0:
141 > args = [self.baseurl, relpaths, start, end, limit, discover_changed_paths,
141 > args = [self.baseurl, relpaths, start, end, limit, discover_changed_paths,
142 warning: line over 80 characters
142 warning: line over 80 characters
143 hgext/convert/subversion.py:0:
143 hgext/convert/subversion.py:0:
144 > self.trunkname = self.ui.config('convert', 'svn.trunk', 'trunk').strip('/')
144 > self.trunkname = self.ui.config('convert', 'svn.trunk', 'trunk').strip('/')
145 warning: line over 80 characters
145 warning: line over 80 characters
146 hgext/convert/subversion.py:0:
146 hgext/convert/subversion.py:0:
147 > except:
147 > except:
148 warning: naked except clause
148 warning: naked except clause
149 hgext/convert/subversion.py:0:
149 hgext/convert/subversion.py:0:
150 > def get_log_child(fp, url, paths, start, end, limit=0, discover_changed_paths=True,
150 > def get_log_child(fp, url, paths, start, end, limit=0, discover_changed_paths=True,
151 warning: line over 80 characters
151 warning: line over 80 characters
152 hgext/eol.py:0:
152 hgext/eol.py:0:
153 > if ui.configbool('eol', 'fix-trailing-newline', False) and s and s[-1] != '\n':
153 > if ui.configbool('eol', 'fix-trailing-newline', False) and s and s[-1] != '\n':
154 warning: line over 80 characters
154 warning: line over 80 characters
155 warning: line over 80 characters
155 warning: line over 80 characters
156 hgext/gpg.py:0:
156 hgext/gpg.py:0:
157 > except:
157 > except:
158 warning: naked except clause
158 warning: naked except clause
159 hgext/hgcia.py:0:
159 hgext/hgcia.py:0:
160 > except:
160 > except:
161 warning: naked except clause
161 warning: naked except clause
162 hgext/hgk.py:0:
162 hgext/hgk.py:0:
163 > ui.write("%s%s\n" % (prefix, description.replace('\n', nlprefix).strip()))
163 > ui.write("%s%s\n" % (prefix, description.replace('\n', nlprefix).strip()))
164 warning: line over 80 characters
164 warning: line over 80 characters
165 hgext/hgk.py:0:
165 hgext/hgk.py:0:
166 > ui.write("parent %s\n" % p)
166 > ui.write("parent %s\n" % p)
167 warning: unwrapped ui message
167 warning: unwrapped ui message
168 hgext/hgk.py:0:
168 hgext/hgk.py:0:
169 > ui.write('k=%s\nv=%s\n' % (name, value))
169 > ui.write('k=%s\nv=%s\n' % (name, value))
170 warning: unwrapped ui message
170 warning: unwrapped ui message
171 hgext/hgk.py:0:
171 hgext/hgk.py:0:
172 > ui.write("author %s %s %s\n" % (ctx.user(), int(date[0]), date[1]))
172 > ui.write("author %s %s %s\n" % (ctx.user(), int(date[0]), date[1]))
173 warning: unwrapped ui message
173 warning: unwrapped ui message
174 hgext/hgk.py:0:
174 hgext/hgk.py:0:
175 > ui.write("branch %s\n\n" % ctx.branch())
175 > ui.write("branch %s\n\n" % ctx.branch())
176 warning: unwrapped ui message
176 warning: unwrapped ui message
177 hgext/hgk.py:0:
177 hgext/hgk.py:0:
178 > ui.write("committer %s %s %s\n" % (committer, int(date[0]), date[1]))
178 > ui.write("committer %s %s %s\n" % (committer, int(date[0]), date[1]))
179 warning: unwrapped ui message
179 warning: unwrapped ui message
180 hgext/hgk.py:0:
180 hgext/hgk.py:0:
181 > ui.write("revision %d\n" % ctx.rev())
181 > ui.write("revision %d\n" % ctx.rev())
182 warning: unwrapped ui message
182 warning: unwrapped ui message
183 hgext/hgk.py:0:
183 hgext/hgk.py:0:
184 > ui.write("tree %s\n" % short(ctx.changeset()[0])) # use ctx.node() instead ??
184 > ui.write("tree %s\n" % short(ctx.changeset()[0])) # use ctx.node() instead ??
185 warning: line over 80 characters
185 warning: line over 80 characters
186 warning: unwrapped ui message
186 warning: unwrapped ui message
187 hgext/highlight/__init__.py:0:
187 hgext/highlight/__init__.py:0:
188 > extensions.wrapfunction(webcommands, '_filerevision', filerevision_highlight)
188 > extensions.wrapfunction(webcommands, '_filerevision', filerevision_highlight)
189 warning: line over 80 characters
189 warning: line over 80 characters
190 hgext/highlight/__init__.py:0:
190 hgext/highlight/__init__.py:0:
191 > return ['/* pygments_style = %s */\n\n' % pg_style, fmter.get_style_defs('')]
191 > return ['/* pygments_style = %s */\n\n' % pg_style, fmter.get_style_defs('')]
192 warning: line over 80 characters
192 warning: line over 80 characters
193 hgext/inotify/__init__.py:0:
193 hgext/inotify/__init__.py:0:
194 > if self._inotifyon and not ignored and not subrepos and not self._dirty:
194 > if self._inotifyon and not ignored and not subrepos and not self._dirty:
195 warning: line over 80 characters
195 warning: line over 80 characters
196 hgext/inotify/server.py:0:
196 hgext/inotify/server.py:0:
197 > except:
197 > except:
198 warning: naked except clause
198 warning: naked except clause
199 hgext/inotify/server.py:0:
199 hgext/inotify/server.py:0:
200 > except:
200 > except:
201 warning: naked except clause
201 warning: naked except clause
202 hgext/keyword.py:0:
202 hgext/keyword.py:0:
203 > ui.note("hg ci -m '%s'\n" % msg)
203 > ui.note("hg ci -m '%s'\n" % msg)
204 warning: unwrapped ui message
204 warning: unwrapped ui message
205 hgext/largefiles/overrides.py:0:
206 > # When we call orig below it creates the standins but we don't add them
207 warning: line over 80 characters
208 hgext/largefiles/reposetup.py:0:
209 > if os.path.exists(self.wjoin(lfutil.standin(lfile))):
210 warning: line over 80 characters
211 hgext/mq.py:0:
205 hgext/mq.py:0:
212 > raise util.Abort(_("cannot push --exact with applied patches"))
206 > raise util.Abort(_("cannot push --exact with applied patches"))
213 warning: line over 80 characters
207 warning: line over 80 characters
214 hgext/mq.py:0:
208 hgext/mq.py:0:
215 > raise util.Abort(_("cannot use --exact and --move together"))
209 > raise util.Abort(_("cannot use --exact and --move together"))
216 warning: line over 80 characters
210 warning: line over 80 characters
217 hgext/mq.py:0:
211 hgext/mq.py:0:
218 > self.ui.warn(_('Tag %s overrides mq patch of the same name\n')
212 > self.ui.warn(_('Tag %s overrides mq patch of the same name\n')
219 warning: line over 80 characters
213 warning: line over 80 characters
220 hgext/mq.py:0:
214 hgext/mq.py:0:
221 > except:
215 > except:
222 warning: naked except clause
216 warning: naked except clause
223 warning: naked except clause
217 warning: naked except clause
224 hgext/mq.py:0:
218 hgext/mq.py:0:
225 > except:
219 > except:
226 warning: naked except clause
220 warning: naked except clause
227 warning: naked except clause
221 warning: naked except clause
228 warning: naked except clause
222 warning: naked except clause
229 warning: naked except clause
223 warning: naked except clause
230 hgext/mq.py:0:
224 hgext/mq.py:0:
231 > raise util.Abort(_('cannot mix -l/--list with options or arguments'))
225 > raise util.Abort(_('cannot mix -l/--list with options or arguments'))
232 warning: line over 80 characters
226 warning: line over 80 characters
233 hgext/mq.py:0:
227 hgext/mq.py:0:
234 > raise util.Abort(_('qfold cannot fold already applied patch %s') % p)
228 > raise util.Abort(_('qfold cannot fold already applied patch %s') % p)
235 warning: line over 80 characters
229 warning: line over 80 characters
236 hgext/mq.py:0:
230 hgext/mq.py:0:
237 > ('', 'move', None, _('reorder patch series and apply only the patch'))],
231 > ('', 'move', None, _('reorder patch series and apply only the patch'))],
238 warning: line over 80 characters
232 warning: line over 80 characters
239 hgext/mq.py:0:
233 hgext/mq.py:0:
240 > ('U', 'noupdate', None, _('do not update the new working directories')),
234 > ('U', 'noupdate', None, _('do not update the new working directories')),
241 warning: line over 80 characters
235 warning: line over 80 characters
242 hgext/mq.py:0:
236 hgext/mq.py:0:
243 > ('e', 'exact', None, _('apply the target patch to its recorded parent')),
237 > ('e', 'exact', None, _('apply the target patch to its recorded parent')),
244 warning: line over 80 characters
238 warning: line over 80 characters
245 hgext/mq.py:0:
239 hgext/mq.py:0:
246 > except:
240 > except:
247 warning: naked except clause
241 warning: naked except clause
248 hgext/mq.py:0:
242 hgext/mq.py:0:
249 > ui.write("mq: %s\n" % ', '.join(m))
243 > ui.write("mq: %s\n" % ', '.join(m))
250 warning: unwrapped ui message
244 warning: unwrapped ui message
251 hgext/mq.py:0:
245 hgext/mq.py:0:
252 > repo.mq.qseries(repo, missing=opts.get('missing'), summary=opts.get('summary'))
246 > repo.mq.qseries(repo, missing=opts.get('missing'), summary=opts.get('summary'))
253 warning: line over 80 characters
247 warning: line over 80 characters
254 hgext/notify.py:0:
248 hgext/notify.py:0:
255 > ui.note(_('notify: suppressing notification for merge %d:%s\n') %
249 > ui.note(_('notify: suppressing notification for merge %d:%s\n') %
256 warning: line over 80 characters
250 warning: line over 80 characters
257 hgext/patchbomb.py:0:
251 hgext/patchbomb.py:0:
258 > binnode, seqno=idx, total=total)
252 > binnode, seqno=idx, total=total)
259 warning: line over 80 characters
253 warning: line over 80 characters
260 hgext/patchbomb.py:0:
254 hgext/patchbomb.py:0:
261 > except:
255 > except:
262 warning: naked except clause
256 warning: naked except clause
263 hgext/patchbomb.py:0:
257 hgext/patchbomb.py:0:
264 > ui.write('Subject: %s\n' % subj)
258 > ui.write('Subject: %s\n' % subj)
265 warning: unwrapped ui message
259 warning: unwrapped ui message
266 hgext/patchbomb.py:0:
260 hgext/patchbomb.py:0:
267 > p = mail.mimetextpatch('\n'.join(patchlines), 'x-patch', opts.get('test'))
261 > p = mail.mimetextpatch('\n'.join(patchlines), 'x-patch', opts.get('test'))
268 warning: line over 80 characters
262 warning: line over 80 characters
269 hgext/patchbomb.py:0:
263 hgext/patchbomb.py:0:
270 > ui.write('From: %s\n' % sender)
264 > ui.write('From: %s\n' % sender)
271 warning: unwrapped ui message
265 warning: unwrapped ui message
272 hgext/record.py:0:
266 hgext/record.py:0:
273 > ignoreblanklines=opts.get('ignore_blank_lines'))
267 > ignoreblanklines=opts.get('ignore_blank_lines'))
274 warning: line over 80 characters
268 warning: line over 80 characters
275 hgext/record.py:0:
269 hgext/record.py:0:
276 > ignorewsamount=opts.get('ignore_space_change'),
270 > ignorewsamount=opts.get('ignore_space_change'),
277 warning: line over 80 characters
271 warning: line over 80 characters
278 hgext/zeroconf/__init__.py:0:
272 hgext/zeroconf/__init__.py:0:
279 > publish(name, desc, path, util.getport(u.config("web", "port", 8000)))
273 > publish(name, desc, path, util.getport(u.config("web", "port", 8000)))
280 warning: line over 80 characters
274 warning: line over 80 characters
281 hgext/zeroconf/__init__.py:0:
275 hgext/zeroconf/__init__.py:0:
282 > except:
276 > except:
283 warning: naked except clause
277 warning: naked except clause
284 warning: naked except clause
278 warning: naked except clause
285 mercurial/bundlerepo.py:0:
279 mercurial/bundlerepo.py:0:
286 > is a bundlerepo for the obtained bundle when the original "other" is remote.
280 > is a bundlerepo for the obtained bundle when the original "other" is remote.
287 warning: line over 80 characters
281 warning: line over 80 characters
288 mercurial/bundlerepo.py:0:
282 mercurial/bundlerepo.py:0:
289 > "local" is a local repo from which to obtain the actual incoming changesets; it
283 > "local" is a local repo from which to obtain the actual incoming changesets; it
290 warning: line over 80 characters
284 warning: line over 80 characters
291 mercurial/bundlerepo.py:0:
285 mercurial/bundlerepo.py:0:
292 > tmp = discovery.findcommonincoming(repo, other, heads=onlyheads, force=force)
286 > tmp = discovery.findcommonincoming(repo, other, heads=onlyheads, force=force)
293 warning: line over 80 characters
287 warning: line over 80 characters
294 mercurial/commands.py:0:
288 mercurial/commands.py:0:
295 > " size " + basehdr + " link p1 p2 nodeid\n")
289 > " size " + basehdr + " link p1 p2 nodeid\n")
296 warning: line over 80 characters
290 warning: line over 80 characters
297 mercurial/commands.py:0:
291 mercurial/commands.py:0:
298 > raise util.Abort('cannot use localheads with old style discovery')
292 > raise util.Abort('cannot use localheads with old style discovery')
299 warning: line over 80 characters
293 warning: line over 80 characters
300 mercurial/commands.py:0:
294 mercurial/commands.py:0:
301 > ui.note('branch %s\n' % data)
295 > ui.note('branch %s\n' % data)
302 warning: unwrapped ui message
296 warning: unwrapped ui message
303 mercurial/commands.py:0:
297 mercurial/commands.py:0:
304 > ui.note('node %s\n' % str(data))
298 > ui.note('node %s\n' % str(data))
305 warning: unwrapped ui message
299 warning: unwrapped ui message
306 mercurial/commands.py:0:
300 mercurial/commands.py:0:
307 > ui.note('tag %s\n' % name)
301 > ui.note('tag %s\n' % name)
308 warning: unwrapped ui message
302 warning: unwrapped ui message
309 mercurial/commands.py:0:
303 mercurial/commands.py:0:
310 > ui.write("unpruned common: %s\n" % " ".join([short(n)
304 > ui.write("unpruned common: %s\n" % " ".join([short(n)
311 warning: unwrapped ui message
305 warning: unwrapped ui message
312 mercurial/commands.py:0:
306 mercurial/commands.py:0:
313 > yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
307 > yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
314 warning: line over 80 characters
308 warning: line over 80 characters
315 mercurial/commands.py:0:
309 mercurial/commands.py:0:
316 > yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
310 > yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
317 warning: line over 80 characters
311 warning: line over 80 characters
318 mercurial/commands.py:0:
312 mercurial/commands.py:0:
319 > except:
313 > except:
320 warning: naked except clause
314 warning: naked except clause
321 mercurial/commands.py:0:
315 mercurial/commands.py:0:
322 > ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
316 > ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
323 warning: line over 80 characters
317 warning: line over 80 characters
324 mercurial/commands.py:0:
318 mercurial/commands.py:0:
325 > ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
319 > ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
326 warning: unwrapped ui message
320 warning: unwrapped ui message
327 mercurial/commands.py:0:
321 mercurial/commands.py:0:
328 > ui.write("local is subset\n")
322 > ui.write("local is subset\n")
329 warning: unwrapped ui message
323 warning: unwrapped ui message
330 mercurial/commands.py:0:
324 mercurial/commands.py:0:
331 > ui.write("remote is subset\n")
325 > ui.write("remote is subset\n")
332 warning: unwrapped ui message
326 warning: unwrapped ui message
333 mercurial/commands.py:0:
327 mercurial/commands.py:0:
334 > ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
328 > ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
335 warning: line over 80 characters
329 warning: line over 80 characters
336 mercurial/commands.py:0:
330 mercurial/commands.py:0:
337 > ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
331 > ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
338 warning: line over 80 characters
332 warning: line over 80 characters
339 mercurial/commands.py:0:
333 mercurial/commands.py:0:
340 > ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
334 > ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
341 warning: line over 80 characters
335 warning: line over 80 characters
342 mercurial/commands.py:0:
336 mercurial/commands.py:0:
343 > ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
337 > ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
344 warning: line over 80 characters
338 warning: line over 80 characters
345 warning: unwrapped ui message
339 warning: unwrapped ui message
346 mercurial/commands.py:0:
340 mercurial/commands.py:0:
347 > ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
341 > ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
348 warning: unwrapped ui message
342 warning: unwrapped ui message
349 mercurial/commands.py:0:
343 mercurial/commands.py:0:
350 > ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
344 > ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
351 warning: unwrapped ui message
345 warning: unwrapped ui message
352 mercurial/commands.py:0:
346 mercurial/commands.py:0:
353 > cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
347 > cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
354 warning: line over 80 characters
348 warning: line over 80 characters
355 mercurial/commands.py:0:
349 mercurial/commands.py:0:
356 > except:
350 > except:
357 warning: naked except clause
351 warning: naked except clause
358 mercurial/commands.py:0:
352 mercurial/commands.py:0:
359 > revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
353 > revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
360 warning: line over 80 characters
354 warning: line over 80 characters
361 mercurial/commands.py:0:
355 mercurial/commands.py:0:
362 > ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
356 > ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
363 warning: unwrapped ui message
357 warning: unwrapped ui message
364 mercurial/commands.py:0:
358 mercurial/commands.py:0:
365 > ui.write("match: %s\n" % m(d[0]))
359 > ui.write("match: %s\n" % m(d[0]))
366 warning: unwrapped ui message
360 warning: unwrapped ui message
367 mercurial/commands.py:0:
361 mercurial/commands.py:0:
368 > ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
362 > ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
369 warning: unwrapped ui message
363 warning: unwrapped ui message
370 mercurial/commands.py:0:
364 mercurial/commands.py:0:
371 > ui.write('path %s\n' % k)
365 > ui.write('path %s\n' % k)
372 warning: unwrapped ui message
366 warning: unwrapped ui message
373 mercurial/commands.py:0:
367 mercurial/commands.py:0:
374 > ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
368 > ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
375 warning: unwrapped ui message
369 warning: unwrapped ui message
376 mercurial/commands.py:0:
370 mercurial/commands.py:0:
377 > Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
371 > Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
378 warning: line over 80 characters
372 warning: line over 80 characters
379 mercurial/commands.py:0:
373 mercurial/commands.py:0:
380 > remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
374 > remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
381 warning: line over 80 characters
375 warning: line over 80 characters
382 mercurial/commands.py:0:
376 mercurial/commands.py:0:
383 > ui.write("digraph G {\n")
377 > ui.write("digraph G {\n")
384 warning: unwrapped ui message
378 warning: unwrapped ui message
385 mercurial/commands.py:0:
379 mercurial/commands.py:0:
386 > ui.write("internal: %s %s\n" % d)
380 > ui.write("internal: %s %s\n" % d)
387 warning: unwrapped ui message
381 warning: unwrapped ui message
388 mercurial/commands.py:0:
382 mercurial/commands.py:0:
389 > ui.write("standard: %s\n" % util.datestr(d))
383 > ui.write("standard: %s\n" % util.datestr(d))
390 warning: unwrapped ui message
384 warning: unwrapped ui message
391 mercurial/commands.py:0:
385 mercurial/commands.py:0:
392 > ui.write('avg chain length : ' + fmt % avgchainlen)
386 > ui.write('avg chain length : ' + fmt % avgchainlen)
393 warning: unwrapped ui message
387 warning: unwrapped ui message
394 mercurial/commands.py:0:
388 mercurial/commands.py:0:
395 > ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
389 > ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
396 warning: unwrapped ui message
390 warning: unwrapped ui message
397 mercurial/commands.py:0:
391 mercurial/commands.py:0:
398 > ui.write('compression ratio : ' + fmt % compratio)
392 > ui.write('compression ratio : ' + fmt % compratio)
399 warning: unwrapped ui message
393 warning: unwrapped ui message
400 mercurial/commands.py:0:
394 mercurial/commands.py:0:
401 > ui.write('delta size (min/max/avg) : %d / %d / %d\n'
395 > ui.write('delta size (min/max/avg) : %d / %d / %d\n'
402 warning: unwrapped ui message
396 warning: unwrapped ui message
403 mercurial/commands.py:0:
397 mercurial/commands.py:0:
404 > ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
398 > ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
405 warning: unwrapped ui message
399 warning: unwrapped ui message
406 mercurial/commands.py:0:
400 mercurial/commands.py:0:
407 > ui.write('flags : %s\n' % ', '.join(flags))
401 > ui.write('flags : %s\n' % ', '.join(flags))
408 warning: unwrapped ui message
402 warning: unwrapped ui message
409 mercurial/commands.py:0:
403 mercurial/commands.py:0:
410 > ui.write('format : %d\n' % format)
404 > ui.write('format : %d\n' % format)
411 warning: unwrapped ui message
405 warning: unwrapped ui message
412 mercurial/commands.py:0:
406 mercurial/commands.py:0:
413 > ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
407 > ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
414 warning: unwrapped ui message
408 warning: unwrapped ui message
415 mercurial/commands.py:0:
409 mercurial/commands.py:0:
416 > ui.write('revision size : ' + fmt2 % totalsize)
410 > ui.write('revision size : ' + fmt2 % totalsize)
417 warning: unwrapped ui message
411 warning: unwrapped ui message
418 mercurial/commands.py:0:
412 mercurial/commands.py:0:
419 > ui.write('revisions : ' + fmt2 % numrevs)
413 > ui.write('revisions : ' + fmt2 % numrevs)
420 warning: unwrapped ui message
414 warning: unwrapped ui message
421 warning: unwrapped ui message
415 warning: unwrapped ui message
422 mercurial/commands.py:0:
416 mercurial/commands.py:0:
423 > ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
417 > ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
424 warning: unwrapped ui message
418 warning: unwrapped ui message
425 mercurial/commandserver.py:0:
419 mercurial/commandserver.py:0:
426 > # the ui here is really the repo ui so take its baseui so we don't end up
420 > # the ui here is really the repo ui so take its baseui so we don't end up
427 warning: line over 80 characters
421 warning: line over 80 characters
428 mercurial/context.py:0:
422 mercurial/context.py:0:
429 > return self._manifestdelta[path], self._manifestdelta.flags(path)
423 > return self._manifestdelta[path], self._manifestdelta.flags(path)
430 warning: line over 80 characters
424 warning: line over 80 characters
431 mercurial/dagparser.py:0:
425 mercurial/dagparser.py:0:
432 > raise util.Abort(_("invalid character in dag description: %s...") % s)
426 > raise util.Abort(_("invalid character in dag description: %s...") % s)
433 warning: line over 80 characters
427 warning: line over 80 characters
434 mercurial/dagparser.py:0:
428 mercurial/dagparser.py:0:
435 > >>> dagtext([('n', (0, [-1])), ('C', 'my command line'), ('n', (1, [0]))])
429 > >>> dagtext([('n', (0, [-1])), ('C', 'my command line'), ('n', (1, [0]))])
436 warning: line over 80 characters
430 warning: line over 80 characters
437 mercurial/dirstate.py:0:
431 mercurial/dirstate.py:0:
438 > if not st is None and not getkind(st.st_mode) in (regkind, lnkkind):
432 > if not st is None and not getkind(st.st_mode) in (regkind, lnkkind):
439 warning: line over 80 characters
433 warning: line over 80 characters
440 mercurial/discovery.py:0:
434 mercurial/discovery.py:0:
441 > If onlyheads is given, only nodes ancestral to nodes in onlyheads (inclusive)
435 > If onlyheads is given, only nodes ancestral to nodes in onlyheads (inclusive)
442 warning: line over 80 characters
436 warning: line over 80 characters
443 mercurial/discovery.py:0:
437 mercurial/discovery.py:0:
444 > def findcommonoutgoing(repo, other, onlyheads=None, force=False, commoninc=None):
438 > def findcommonoutgoing(repo, other, onlyheads=None, force=False, commoninc=None):
445 warning: line over 80 characters
439 warning: line over 80 characters
446 mercurial/dispatch.py:0:
440 mercurial/dispatch.py:0:
447 > " (.hg not found)") % os.getcwd())
441 > " (.hg not found)") % os.getcwd())
448 warning: line over 80 characters
442 warning: line over 80 characters
449 mercurial/dispatch.py:0:
443 mercurial/dispatch.py:0:
450 > aliases, entry = cmdutil.findcmd(cmd, cmdtable, lui.config("ui", "strict"))
444 > aliases, entry = cmdutil.findcmd(cmd, cmdtable, lui.config("ui", "strict"))
451 warning: line over 80 characters
445 warning: line over 80 characters
452 mercurial/dispatch.py:0:
446 mercurial/dispatch.py:0:
453 > except:
447 > except:
454 warning: naked except clause
448 warning: naked except clause
455 mercurial/dispatch.py:0:
449 mercurial/dispatch.py:0:
456 > return lambda: runcommand(lui, None, cmd, args[:1], ui, options, d, [], {})
450 > return lambda: runcommand(lui, None, cmd, args[:1], ui, options, d, [], {})
457 warning: line over 80 characters
451 warning: line over 80 characters
458 mercurial/dispatch.py:0:
452 mercurial/dispatch.py:0:
459 > def __init__(self, args, ui=None, repo=None, fin=None, fout=None, ferr=None):
453 > def __init__(self, args, ui=None, repo=None, fin=None, fout=None, ferr=None):
460 warning: line over 80 characters
454 warning: line over 80 characters
461 mercurial/dispatch.py:0:
455 mercurial/dispatch.py:0:
462 > except:
456 > except:
463 warning: naked except clause
457 warning: naked except clause
464 mercurial/hg.py:0:
458 mercurial/hg.py:0:
465 > except:
459 > except:
466 warning: naked except clause
460 warning: naked except clause
467 mercurial/hgweb/hgweb_mod.py:0:
461 mercurial/hgweb/hgweb_mod.py:0:
468 > self.maxshortchanges = int(self.config("web", "maxshortchanges", 60))
462 > self.maxshortchanges = int(self.config("web", "maxshortchanges", 60))
469 warning: line over 80 characters
463 warning: line over 80 characters
470 mercurial/keepalive.py:0:
464 mercurial/keepalive.py:0:
471 > except:
465 > except:
472 warning: naked except clause
466 warning: naked except clause
473 mercurial/keepalive.py:0:
467 mercurial/keepalive.py:0:
474 > except:
468 > except:
475 warning: naked except clause
469 warning: naked except clause
476 mercurial/localrepo.py:0:
470 mercurial/localrepo.py:0:
477 > # we return an integer indicating remote head count change
471 > # we return an integer indicating remote head count change
478 warning: line over 80 characters
472 warning: line over 80 characters
479 mercurial/localrepo.py:0:
473 mercurial/localrepo.py:0:
480 > raise util.Abort(_("empty or missing revlog for %s") % fname)
474 > raise util.Abort(_("empty or missing revlog for %s") % fname)
481 warning: line over 80 characters
475 warning: line over 80 characters
482 warning: line over 80 characters
476 warning: line over 80 characters
483 mercurial/localrepo.py:0:
477 mercurial/localrepo.py:0:
484 > if self._tagscache.tagtypes and name in self._tagscache.tagtypes:
478 > if self._tagscache.tagtypes and name in self._tagscache.tagtypes:
485 warning: line over 80 characters
479 warning: line over 80 characters
486 mercurial/localrepo.py:0:
480 mercurial/localrepo.py:0:
487 > self.hook("precommit", throw=True, parent1=hookp1, parent2=hookp2)
481 > self.hook("precommit", throw=True, parent1=hookp1, parent2=hookp2)
488 warning: line over 80 characters
482 warning: line over 80 characters
489 mercurial/localrepo.py:0:
483 mercurial/localrepo.py:0:
490 > # new requirements = old non-format requirements + new format-related
484 > # new requirements = old non-format requirements + new format-related
491 warning: line over 80 characters
485 warning: line over 80 characters
492 mercurial/localrepo.py:0:
486 mercurial/localrepo.py:0:
493 > except:
487 > except:
494 warning: naked except clause
488 warning: naked except clause
495 mercurial/localrepo.py:0:
489 mercurial/localrepo.py:0:
496 > """return status of files between two nodes or node and working directory
490 > """return status of files between two nodes or node and working directory
497 warning: line over 80 characters
491 warning: line over 80 characters
498 mercurial/localrepo.py:0:
492 mercurial/localrepo.py:0:
499 > '''Returns a tagscache object that contains various tags related caches.'''
493 > '''Returns a tagscache object that contains various tags related caches.'''
500 warning: line over 80 characters
494 warning: line over 80 characters
501 mercurial/manifest.py:0:
495 mercurial/manifest.py:0:
502 > return "".join(struct.pack(">lll", start, end, len(content)) + content
496 > return "".join(struct.pack(">lll", start, end, len(content)) + content
503 warning: line over 80 characters
497 warning: line over 80 characters
504 mercurial/merge.py:0:
498 mercurial/merge.py:0:
505 > subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx), overwrite)
499 > subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx), overwrite)
506 warning: line over 80 characters
500 warning: line over 80 characters
507 mercurial/patch.py:0:
501 mercurial/patch.py:0:
508 > modified, added, removed, copy, getfilectx, opts, losedata, prefix)
502 > modified, added, removed, copy, getfilectx, opts, losedata, prefix)
509 warning: line over 80 characters
503 warning: line over 80 characters
510 mercurial/patch.py:0:
504 mercurial/patch.py:0:
511 > diffhelpers.addlines(lr, self.hunk, self.lena, self.lenb, self.a, self.b)
505 > diffhelpers.addlines(lr, self.hunk, self.lena, self.lenb, self.a, self.b)
512 warning: line over 80 characters
506 warning: line over 80 characters
513 mercurial/patch.py:0:
507 mercurial/patch.py:0:
514 > output.append(_(' %d files changed, %d insertions(+), %d deletions(-)\n')
508 > output.append(_(' %d files changed, %d insertions(+), %d deletions(-)\n')
515 warning: line over 80 characters
509 warning: line over 80 characters
516 mercurial/patch.py:0:
510 mercurial/patch.py:0:
517 > except:
511 > except:
518 warning: naked except clause
512 warning: naked except clause
519 mercurial/pure/base85.py:0:
513 mercurial/pure/base85.py:0:
520 > raise OverflowError('Base85 overflow in hunk starting at byte %d' % i)
514 > raise OverflowError('Base85 overflow in hunk starting at byte %d' % i)
521 warning: line over 80 characters
515 warning: line over 80 characters
522 mercurial/pure/mpatch.py:0:
516 mercurial/pure/mpatch.py:0:
523 > frags.extend(reversed(new)) # what was left at the end
517 > frags.extend(reversed(new)) # what was left at the end
524 warning: line over 80 characters
518 warning: line over 80 characters
525 mercurial/repair.py:0:
519 mercurial/repair.py:0:
526 > except:
520 > except:
527 warning: naked except clause
521 warning: naked except clause
528 mercurial/repair.py:0:
522 mercurial/repair.py:0:
529 > except:
523 > except:
530 warning: naked except clause
524 warning: naked except clause
531 mercurial/revset.py:0:
525 mercurial/revset.py:0:
532 > elif c.isalnum() or c in '._' or ord(c) > 127: # gather up a symbol/keyword
526 > elif c.isalnum() or c in '._' or ord(c) > 127: # gather up a symbol/keyword
533 warning: line over 80 characters
527 warning: line over 80 characters
534 mercurial/revset.py:0:
528 mercurial/revset.py:0:
535 > Changesets that are the Nth ancestor (first parents only) of a changeset in set.
529 > Changesets that are the Nth ancestor (first parents only) of a changeset in set.
536 warning: line over 80 characters
530 warning: line over 80 characters
537 mercurial/scmutil.py:0:
531 mercurial/scmutil.py:0:
538 > raise util.Abort(_("path '%s' is inside nested repo %r") %
532 > raise util.Abort(_("path '%s' is inside nested repo %r") %
539 warning: line over 80 characters
533 warning: line over 80 characters
540 mercurial/scmutil.py:0:
534 mercurial/scmutil.py:0:
541 > "requires features '%s' (upgrade Mercurial)") % "', '".join(missings))
535 > "requires features '%s' (upgrade Mercurial)") % "', '".join(missings))
542 warning: line over 80 characters
536 warning: line over 80 characters
543 mercurial/scmutil.py:0:
537 mercurial/scmutil.py:0:
544 > elif repo.dirstate[abs] != 'r' and (not good or not os.path.lexists(target)
538 > elif repo.dirstate[abs] != 'r' and (not good or not os.path.lexists(target)
545 warning: line over 80 characters
539 warning: line over 80 characters
546 mercurial/setdiscovery.py:0:
540 mercurial/setdiscovery.py:0:
547 > # treat remote heads (and maybe own heads) as a first implicit sample response
541 > # treat remote heads (and maybe own heads) as a first implicit sample response
548 warning: line over 80 characters
542 warning: line over 80 characters
549 mercurial/setdiscovery.py:0:
543 mercurial/setdiscovery.py:0:
550 > undecided = dag.nodeset() # own nodes where I don't know if remote knows them
544 > undecided = dag.nodeset() # own nodes where I don't know if remote knows them
551 warning: line over 80 characters
545 warning: line over 80 characters
552 mercurial/similar.py:0:
546 mercurial/similar.py:0:
553 > repo.ui.progress(_('searching for similar files'), i, total=len(removed))
547 > repo.ui.progress(_('searching for similar files'), i, total=len(removed))
554 warning: line over 80 characters
548 warning: line over 80 characters
555 mercurial/simplemerge.py:0:
549 mercurial/simplemerge.py:0:
556 > for zmatch, zend, amatch, aend, bmatch, bend in self.find_sync_regions():
550 > for zmatch, zend, amatch, aend, bmatch, bend in self.find_sync_regions():
557 warning: line over 80 characters
551 warning: line over 80 characters
558 mercurial/sshrepo.py:0:
552 mercurial/sshrepo.py:0:
559 > self._abort(error.RepoError(_("no suitable response from remote hg")))
553 > self._abort(error.RepoError(_("no suitable response from remote hg")))
560 warning: line over 80 characters
554 warning: line over 80 characters
561 mercurial/sshrepo.py:0:
555 mercurial/sshrepo.py:0:
562 > except:
556 > except:
563 warning: naked except clause
557 warning: naked except clause
564 mercurial/subrepo.py:0:
558 mercurial/subrepo.py:0:
565 > other, self._repo = hg.clone(self._repo._subparent.ui, {}, other,
559 > other, self._repo = hg.clone(self._repo._subparent.ui, {}, other,
566 warning: line over 80 characters
560 warning: line over 80 characters
567 mercurial/subrepo.py:0:
561 mercurial/subrepo.py:0:
568 > msg = (_(' subrepository sources for %s differ (in checked out version)\n'
562 > msg = (_(' subrepository sources for %s differ (in checked out version)\n'
569 warning: line over 80 characters
563 warning: line over 80 characters
570 mercurial/transaction.py:0:
564 mercurial/transaction.py:0:
571 > except:
565 > except:
572 warning: naked except clause
566 warning: naked except clause
573 mercurial/ui.py:0:
567 mercurial/ui.py:0:
574 > traceback.print_exception(exc[0], exc[1], exc[2], file=self.ferr)
568 > traceback.print_exception(exc[0], exc[1], exc[2], file=self.ferr)
575 warning: line over 80 characters
569 warning: line over 80 characters
576 mercurial/url.py:0:
570 mercurial/url.py:0:
577 > conn = httpsconnection(host, port, keyfile, certfile, *args, **kwargs)
571 > conn = httpsconnection(host, port, keyfile, certfile, *args, **kwargs)
578 warning: line over 80 characters
572 warning: line over 80 characters
579 mercurial/util.py:0:
573 mercurial/util.py:0:
580 > except:
574 > except:
581 warning: naked except clause
575 warning: naked except clause
582 mercurial/util.py:0:
576 mercurial/util.py:0:
583 > except:
577 > except:
584 warning: naked except clause
578 warning: naked except clause
585 mercurial/verify.py:0:
579 mercurial/verify.py:0:
586 > except:
580 > except:
587 warning: naked except clause
581 warning: naked except clause
588 mercurial/verify.py:0:
582 mercurial/verify.py:0:
589 > except:
583 > except:
590 warning: naked except clause
584 warning: naked except clause
591 mercurial/wireproto.py:0:
585 mercurial/wireproto.py:0:
592 > # Assuming the future to be filled with the result from the batched request
586 > # Assuming the future to be filled with the result from the batched request
593 warning: line over 80 characters
587 warning: line over 80 characters
594 mercurial/wireproto.py:0:
588 mercurial/wireproto.py:0:
595 > '''remote must support _submitbatch(encbatch) and _submitone(op, encargs)'''
589 > '''remote must support _submitbatch(encbatch) and _submitone(op, encargs)'''
596 warning: line over 80 characters
590 warning: line over 80 characters
597 mercurial/wireproto.py:0:
591 mercurial/wireproto.py:0:
598 > All methods invoked on instances of this class are simply queued and return a
592 > All methods invoked on instances of this class are simply queued and return a
599 warning: line over 80 characters
593 warning: line over 80 characters
600 mercurial/wireproto.py:0:
594 mercurial/wireproto.py:0:
601 > The decorator returns a function which wraps this coroutine as a plain method,
595 > The decorator returns a function which wraps this coroutine as a plain method,
602 warning: line over 80 characters
596 warning: line over 80 characters
603 setup.py:0:
597 setup.py:0:
604 > raise SystemExit("Python headers are required to build Mercurial")
598 > raise SystemExit("Python headers are required to build Mercurial")
605 warning: line over 80 characters
599 warning: line over 80 characters
606 setup.py:0:
600 setup.py:0:
607 > except:
601 > except:
608 warning: naked except clause
602 warning: naked except clause
609 setup.py:0:
603 setup.py:0:
610 > # build_py), it will not find osutil & friends, thinking that those modules are
604 > # build_py), it will not find osutil & friends, thinking that those modules are
611 warning: line over 80 characters
605 warning: line over 80 characters
612 setup.py:0:
606 setup.py:0:
613 > except:
607 > except:
614 warning: naked except clause
608 warning: naked except clause
615 warning: naked except clause
609 warning: naked except clause
616 setup.py:0:
610 setup.py:0:
617 > isironpython = platform.python_implementation().lower().find("ironpython") != -1
611 > isironpython = platform.python_implementation().lower().find("ironpython") != -1
618 warning: line over 80 characters
612 warning: line over 80 characters
619 setup.py:0:
613 setup.py:0:
620 > except:
614 > except:
621 warning: naked except clause
615 warning: naked except clause
622 warning: naked except clause
616 warning: naked except clause
623 warning: naked except clause
617 warning: naked except clause
624 tests/autodiff.py:0:
618 tests/autodiff.py:0:
625 > ui.write('data lost for: %s\n' % fn)
619 > ui.write('data lost for: %s\n' % fn)
626 warning: unwrapped ui message
620 warning: unwrapped ui message
627 tests/run-tests.py:0:
621 tests/run-tests.py:0:
628 > except:
622 > except:
629 warning: naked except clause
623 warning: naked except clause
630 tests/test-commandserver.py:0:
624 tests/test-commandserver.py:0:
631 > 'hooks.pre-identify=python:test-commandserver.hook', 'id'],
625 > 'hooks.pre-identify=python:test-commandserver.hook', 'id'],
632 warning: line over 80 characters
626 warning: line over 80 characters
633 tests/test-commandserver.py:0:
627 tests/test-commandserver.py:0:
634 > # the cached repo local hgrc contains ui.foo=bar, so showconfig should show it
628 > # the cached repo local hgrc contains ui.foo=bar, so showconfig should show it
635 warning: line over 80 characters
629 warning: line over 80 characters
636 tests/test-commandserver.py:0:
630 tests/test-commandserver.py:0:
637 > print '%c, %r' % (ch, re.sub('encoding: [a-zA-Z0-9-]+', 'encoding: ***', data))
631 > print '%c, %r' % (ch, re.sub('encoding: [a-zA-Z0-9-]+', 'encoding: ***', data))
638 warning: line over 80 characters
632 warning: line over 80 characters
639 tests/test-filecache.py:0:
633 tests/test-filecache.py:0:
640 > except:
634 > except:
641 warning: naked except clause
635 warning: naked except clause
642 tests/test-filecache.py:0:
636 tests/test-filecache.py:0:
643 > if subprocess.call(['python', '%s/hghave' % os.environ['TESTDIR'], 'cacheable']):
637 > if subprocess.call(['python', '%s/hghave' % os.environ['TESTDIR'], 'cacheable']):
644 warning: line over 80 characters
638 warning: line over 80 characters
645 tests/test-ui-color.py:0:
639 tests/test-ui-color.py:0:
646 > testui.warn('warning\n')
640 > testui.warn('warning\n')
647 warning: unwrapped ui message
641 warning: unwrapped ui message
648 tests/test-ui-color.py:0:
642 tests/test-ui-color.py:0:
649 > testui.write('buffered\n')
643 > testui.write('buffered\n')
650 warning: unwrapped ui message
644 warning: unwrapped ui message
651 tests/test-walkrepo.py:0:
645 tests/test-walkrepo.py:0:
652 > print "Found %d repositories when I should have found 2" % (len(reposet),)
646 > print "Found %d repositories when I should have found 2" % (len(reposet),)
653 warning: line over 80 characters
647 warning: line over 80 characters
654 tests/test-walkrepo.py:0:
648 tests/test-walkrepo.py:0:
655 > print "Found %d repositories when I should have found 3" % (len(reposet),)
649 > print "Found %d repositories when I should have found 3" % (len(reposet),)
656 warning: line over 80 characters
650 warning: line over 80 characters
General Comments 0
You need to be logged in to leave comments. Login now